Improve Alpine Linux support and agent startup validation

Related to #612

This commit addresses the Alpine Linux installation issues reported where:
1. The OpenRC init system was not properly detected
2. Manual startup instructions were unclear and used placeholder values
3. The agent didn't validate configuration properly at startup

Changes:

Install Script (install-docker-agent.sh):
- Improved OpenRC detection to check for rc-service and rc-update commands
  instead of looking for openrc-run binary in specific paths
- Added specific Alpine Linux detection via /etc/alpine-release and /etc/os-release
- Enhanced manual startup instructions to show actual values instead of placeholders
- Added clearer warnings and guidance when no init system is detected
- Included comprehensive startup command with all required parameters

Agent Startup Validation (pulse-docker-agent):
- Added validation to detect unexpected command-line arguments
- Added helpful note about double-dash flag requirements (--token vs -token)
- Improved error messages to include example usage patterns
- Added warning when defaulting to localhost without explicit URL configuration
- Provide both command-line and environment variable examples in error messages

These improvements ensure that:
- Alpine Linux installations will properly detect and configure OpenRC services
- Users who must start the agent manually get clear, copy-pasteable commands
- Configuration errors are caught early with actionable error messages
- Common mistakes (like missing --url) are clearly explained
This commit is contained in:
rcourtman 2025-11-05 19:01:09 +00:00
parent 02864f54dd
commit 3194b10398
2 changed files with 65 additions and 9 deletions

View file

@ -126,7 +126,26 @@ func loadConfig() dockeragent.Config {
flag.Parse()
// Check for common mistakes with unparsed arguments
unparsedArgs := flag.Args()
if len(unparsedArgs) > 0 {
// Check if any look like flags with single dash
for _, arg := range unparsedArgs {
if strings.HasPrefix(arg, "-") && !strings.HasPrefix(arg, "--") {
fmt.Fprintf(os.Stderr, "error: unrecognized argument %q\n", arg)
fmt.Fprintln(os.Stderr, "note: flags must use double dashes (e.g., --token, not -token)")
fmt.Fprintln(os.Stderr, "\nUsage:")
flag.Usage()
os.Exit(1)
}
}
fmt.Fprintf(os.Stderr, "error: unexpected arguments: %v\n", unparsedArgs)
flag.Usage()
os.Exit(1)
}
pulseURL := *urlFlag
urlFromEnvOrFlag := envURL != "" || *urlFlag != envURL
if pulseURL == "" {
pulseURL = "http://localhost:7655"
}
@ -157,10 +176,22 @@ func loadConfig() dockeragent.Config {
token := strings.TrimSpace(*tokenFlag)
if token == "" && len(targets) == 0 {
fmt.Fprintln(os.Stderr, "error: PULSE_TOKEN, --token, or at least one --target/PULSE_TARGETS entry must be provided")
flag.Usage()
fmt.Fprintln(os.Stderr, "\nExample usage:")
fmt.Fprintln(os.Stderr, " pulse-docker-agent --url http://pulse.example.com:7655 --token <your-token>")
fmt.Fprintln(os.Stderr, "\nOr set environment variables:")
fmt.Fprintln(os.Stderr, " export PULSE_URL=http://pulse.example.com:7655")
fmt.Fprintln(os.Stderr, " export PULSE_TOKEN=<your-token>")
fmt.Fprintln(os.Stderr, " pulse-docker-agent")
os.Exit(1)
}
// Warn if using default localhost URL without explicit configuration
if !urlFromEnvOrFlag && len(targets) == 0 && token != "" {
fmt.Fprintln(os.Stderr, "warning: no --url or PULSE_URL provided, defaulting to http://localhost:7655")
fmt.Fprintln(os.Stderr, "note: if your Pulse server is not on localhost, specify --url http://your-pulse-server:7655")
fmt.Fprintln(os.Stderr, "")
}
interval := *intervalFlag
if interval <= 0 {
interval = 30 * time.Second

View file

@ -1511,8 +1511,15 @@ EOF
log_info 'Log file : /var/log/pulse-docker-agent.log'
log_info 'Host visible in Pulse: ~30 seconds'
exit 0
elif command -v rc-service >/dev/null 2>&1 && { [ -x /sbin/openrc-run ] || [ -x /bin/openrc-run ] || [ -x /usr/bin/openrc-run ]; }; then
log_info 'Detected OpenRC environment'
elif command -v rc-service >/dev/null 2>&1 && command -v rc-update >/dev/null 2>&1; then
# Alpine Linux and other OpenRC-based systems
IS_ALPINE="false"
if [ -f /etc/alpine-release ] || grep -qi 'alpine' /etc/os-release 2>/dev/null; then
IS_ALPINE="true"
log_info 'Detected Alpine Linux with OpenRC'
else
log_info 'Detected OpenRC environment'
fi
log_header 'Preparing service environment'
ensure_service_user
@ -1596,12 +1603,30 @@ EOF
log_info 'Manual startup environment detected'
log_info "Binary location : $AGENT_PATH"
log_info 'Start manually with :'
printf ' PULSE_URL=%s PULSE_TOKEN=<api-token> \\n' "$PRIMARY_URL"
printf ' PULSE_TARGETS="%s" \\n' "https://pulse.example.com|<token>[;https://pulse-alt.example.com|<token2>]"
printf ' %s --interval %s &
' "$AGENT_PATH" "$INTERVAL"
log_info 'Add the same command to your init system to start automatically.'
printf '\n'
log_warn 'No supported init system detected (systemd, OpenRC, or Unraid).'
log_warn 'You must start the agent manually and configure it to start on boot.'
printf '\n'
log_info 'Start the agent in the background with:'
printf ' PULSE_URL=%s PULSE_TOKEN=%s \\\n' "$(quote_shell_arg "$PRIMARY_URL")" "$(quote_shell_arg "$PRIMARY_TOKEN")"
if [[ ${#TARGETS[@]} -gt 1 ]]; then
printf ' PULSE_TARGETS=%s \\\n' "$(quote_shell_arg "$JOINED_TARGETS")"
fi
if [[ "$PRIMARY_INSECURE" == "true" ]]; then
printf ' PULSE_INSECURE_SKIP_VERIFY=true \\\n'
fi
printf ' %s --url %s --token %s --interval %s%s > /var/log/pulse-docker-agent.log 2>&1 &\n' \
"$AGENT_PATH" \
"$(quote_shell_arg "$PRIMARY_URL")" \
"$(quote_shell_arg "$PRIMARY_TOKEN")" \
"$INTERVAL" \
"$NO_AUTO_UPDATE_FLAG"
printf '\n'
log_info 'Check if running: ps aux | grep pulse-docker-agent'
log_info 'View logs : tail -f /var/log/pulse-docker-agent.log'
printf '\n'
log_warn 'IMPORTANT: Add the command above to your system startup scripts'
log_warn 'to ensure the agent starts automatically after reboots.'
exit 0
fi