pub struct ServiceOperations { /* private fields */ }Expand description
Install, uninstall, inspect, and switch start mode.
This is the whole of the library contract f3 builds service install,
service uninstall and service status on. Nothing here prints; every
operation returns a value with a fmt::Display a command can write, so the
same facts are available to the TUI and to a JSON document without being
re-derived from text.
Implementations§
Source§impl ServiceOperations
impl ServiceOperations
Sourcepub fn on_this_host(paths: AppPaths) -> Self
pub fn on_this_host(paths: AppPaths) -> Self
Operates on this host’s real service managers.
Sourcepub fn with_controls(
paths: AppPaths,
identity: ServiceIdentity,
controls: Arc<dyn ControlFactory>,
) -> Self
pub fn with_controls( paths: AppPaths, identity: ServiceIdentity, controls: Arc<dyn ControlFactory>, ) -> Self
Operates on the controls a caller supplies.
Both other arguments are explicit for the same reason: the privileged
installer tests register a real service under a
ServiceIdentity::fixture name, against a disposable
AppPaths::rooted_at tree, and must not be able to touch an operator’s
installation even by mistake.
Sourcepub fn with_runner_root(self, root: LocalAbsolutePath) -> Self
pub fn with_runner_root(self, root: LocalAbsolutePath) -> Self
Points runner-root preparation at a directory the caller owns, for the current account.
Only a ServiceIdentity::fixture registration is allowed to move
it, and the guard is here rather than at the call site. A product
registration ignores the override entirely and resolves
crate::runner_root::default_runner_root itself, which is what keeps
“custom roots are never re-ACLed” true no matter what a caller passes.
It exists because the directory the product uses is
%SystemDrive%\rman, and a smoke test that created and re-permissioned
that would be editing the machine it runs on from outside its own
fixture. So a fixture aims this at a temporary directory it created and
will delete — and “and will delete” is why the override is always
reconciled for the calling account rather than for the account the start
mode obliges. A boot-mode root admits SY and BA only, which an
ordinary filtered token is neither, so a test that supplied one could
not then inspect or remove its own temporary directory.
Sourcepub const fn identity(&self) -> &ServiceIdentity
pub const fn identity(&self) -> &ServiceIdentity
The registration this operates on.
Sourcepub fn install(
&self,
request: &InstallRequest,
) -> Result<Installed, ServiceError>
pub fn install( &self, request: &InstallRequest, ) -> Result<Installed, ServiceError>
Registers daemon run with the operating system.
The order is the contract, and each step is a requirement:
- the four directories are created, because item 2 is about writing them;
- the single-instance lock is taken — item 1. It is held for the whole of the install rather than probed and released, so a daemon that starts halfway through cannot end up racing a registration;
- neither start-mode domain already holds a registration — item 6’s record would otherwise describe one of two;
- the binary path is resolved and confirmed to be a file — item 6;
- the platform registers it;
- the record is written.
§Errors
ServiceError::LockHeld when an agent is already running,
ServiceError::AlreadyInstalled, ServiceError::BinaryMissing, and
whatever the platform reports.
Sourcepub fn uninstall(&self) -> Result<Uninstalled, ServiceError>
pub fn uninstall(&self) -> Result<Uninstalled, ServiceError>
Deregisters, and deletes nothing else.
§Errors
Whatever the platform reports. A missing registration is not an
error: service uninstall on a host that has none should say so and
exit cleanly, because an operator running it twice has not made a
mistake.
Sourcepub fn set_start_mode(
&self,
to: StartMode,
) -> Result<StartModeChange, ServiceError>
pub fn set_start_mode( &self, to: StartMode, ) -> Result<StartModeChange, ServiceError>
Switches between boot and login without re-resolving anything.
05-infrastructure.md item 7. Everything the new registration carries —
the absolute binary path, the arguments, the restart policy, the four
directories — comes from the existing record, so the operator is not
asked to reinstall the product and a binary that has since moved is not
silently swapped for whichever one happens to be running this command.
On Windows the registration necessarily moves between two different Windows facilities, because Windows has no service that starts at logon; see this module’s documentation. That is still not a reinstall: no file is downloaded, replaced, or re-resolved.
The caller must persist the new mode onto this host’s Host record so
that host show reports it — StartModeChange::to is the value, and
f1 already emits host.service_start_mode from that field.
§Errors
ServiceError::NotInstalled when there is no record to switch, and
whatever the platform reports.
Sourcepub fn start(&self) -> Result<(), ServiceError>
pub fn start(&self) -> Result<(), ServiceError>
Sourcepub fn stop(&self) -> Result<bool, ServiceError>
pub fn stop(&self) -> Result<bool, ServiceError>
Sourcepub fn status(&self) -> Result<ServiceStatus, ServiceError>
pub fn status(&self) -> Result<ServiceStatus, ServiceError>
Everything Journey 5 step 4 asks service status to report.
§Errors
ServiceError::Record when local state cannot be read, and whatever
the platform reports. A stale binary path is deliberately not an
error here: it is a reported state, because a status command that
refused to print anything else would hide the very facts an operator
needs in order to fix it.
A record this account may not read is reported for the same reason
and is the second exception. On a boot-mode host the record was written
by sudo service install, and a version before this one wrote it 0600
— so the operator’s own service status ended with Permission denied
and printed nothing at all, on a host whose registration the service
manager would have described perfectly well. What launchd, systemd or
the SCM says is a separate fact from the record, and it is still worth
having.
Trait Implementations§
Source§impl Clone for ServiceOperations
impl Clone for ServiceOperations
Source§fn clone(&self) -> ServiceOperations
fn clone(&self) -> ServiceOperations
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more