Service Type
This document describes the design of the service resource type for managing system services.
Overview
The service resource manages system services with two independent dimensions:
- Running state: Whether the service is currently running or stopped
- Enabled state: Whether the service starts automatically at boot
These are managed independently, allowing combinations like “running but disabled” or “stopped but enabled”.
Provider Interface
Service providers must implement the ServiceProvider interface:
Method Responsibilities
| Method | Responsibility |
|---|---|
Status | Query current running and enabled state |
Start | Start the service if not running |
Stop | Stop the service if running |
Restart | Stop and start the service (for refresh) |
Enable | Configure service to start at boot |
Disable | Configure service to not start at boot |
Status Response
The Status method returns a ServiceState containing:
The Ensure field in CommonResourceState is set to:
runningif the service is activestoppedif the service is inactive
Available Providers
| Provider | Init System | Documentation |
|---|---|---|
systemd | systemd | Systemd |
Ensure States
| Value | Description |
|---|---|
running | Service must be running (default) |
stopped | Service must be stopped |
If ensure is not specified, it defaults to running.
Enable Property
The enable property is a boolean pointer (*bool) with three possible states:
| Value | Behavior |
|---|---|
true | Enable service to start at boot |
false | Disable service from starting at boot |
nil (not set) | Leave boot configuration unchanged |
This allows managing running state without affecting boot configuration:
Apply Logic
The service type applies changes in two phases:
Phase 1: Running State
Phase 2: Enabled State
After running state is handled, enabled state is processed:
Subscribe Behavior
Services can subscribe to other resources and restart when they change:
Special Cases:
| Condition | Behavior |
|---|---|
ensure: stopped | Subscribe ignored (no restart) |
Service not running + ensure: running | Start (not restart) |
Service running + ensure: running | Restart |
This prevents restarting stopped services and ensures a clean start when the service should be running but isn’t.
Idempotency
The service resource is idempotent through state comparison:
| Desired | Current | Action |
|---|---|---|
ensure: running | running | None |
ensure: running | stopped | Start |
ensure: stopped | stopped | None |
ensure: stopped | running | Stop |
enable: true | enabled | None |
enable: true | disabled | Enable |
enable: false | enabled | Disable |
enable: false | disabled | None |
enable: nil | any | None |
Desired State Validation
After applying changes, the type verifies the service reached the desired state:
If the desired state is not reached, an ErrDesiredStateFailed error is returned.
Service Name Validation
Service names are validated to prevent injection attacks:
Allowed Characters:
- Alphanumeric (
a-z,A-Z,0-9) - Period (
.), underscore (_), plus (+) - Colon (
:), tilde (~), hyphen (-)
Rejected:
- Shell metacharacters (
;,|,&, etc.) - Whitespace
- Path separators
Noop Mode
In noop mode, the service type:
- Queries current state normally
- Logs what actions would be taken
- Sets appropriate
NoopMessage(e.g., “Would have started”, “Would have enabled”) - Reports
Changed: trueif changes would occur - Does not call provider Start/Stop/Restart/Enable/Disable methods