Skip to main content

ServiceOperations

Struct ServiceOperations 

Source
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

Source

pub fn on_this_host(paths: AppPaths) -> Self

Operates on this host’s real service managers.

Source

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.

Source

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.

Source

pub const fn paths(&self) -> &AppPaths

The directories this operates against.

Source

pub const fn identity(&self) -> &ServiceIdentity

The registration this operates on.

Source

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:

  1. the four directories are created, because item 2 is about writing them;
  2. 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;
  3. neither start-mode domain already holds a registration — item 6’s record would otherwise describe one of two;
  4. the binary path is resolved and confirmed to be a file — item 6;
  5. the platform registers it;
  6. the record is written.
§Errors

ServiceError::LockHeld when an agent is already running, ServiceError::AlreadyInstalled, ServiceError::BinaryMissing, and whatever the platform reports.

Source

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.

Source

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.

Source

pub fn start(&self) -> Result<(), ServiceError>

Starts the registration now.

§Errors

ServiceError::NotInstalled, or whatever the platform reports.

Source

pub fn stop(&self) -> Result<bool, ServiceError>

Stops the registration. Returns whether it was running.

§Errors

As ServiceOperations::start.

Source

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

Source§

fn clone(&self) -> ServiceOperations

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ServiceOperations

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more