Skip to content

Proposal to rewrite the launchd module #10414

@nre-ableton

Description

@nre-ableton

Summary

My organization has a fairly large macOS VM cluster, for which we use Ansible to manage services and such. At the moment, we have a number of boilerplate tasks to do this and we'd like to use the launchd module, but it does not support many of the things that we need. I feel that the launchd module, as it is currently architected, has some big shortcomings and is in need of a rewrite. I am happy to undertake this, but before submitting a "big bang" PR for a very large breaking change, I wanted to gather input from the community to see if this would be at all desirable.

I will detail below the changes that I would propose.

Change the meaning of the start/stop states

In macOS 10.11 (El Capitan), which was released in 2015, the launchctl load/launchctl unload/launchctl start/launchctl stop commands were replaced by launchctl bootstrap/launchctl bootout. The old commands remain in place to this day but are considered deprecated. Apple has (predictably) not given any public timeline for removing them, but they could disappear spontaneously in any new macOS release.

We should get rid of the old actions and replace them with bootstrap/bootout. Unfortunately, "bootout" does not lend itself nicely to a past tense verb for state, so I would suggest replacing the behavior of started/stopped with launchctl bootstrap/launchctl bootout instead. This could be a bit confusing, so we'll need to document it well. The loaded/unloaded states will be deprecated and removed in a future release.

Note that the new behavior for these actions will require a user ID, which will be obtained from the owner parameter (see below).

Add new states for enabled/disabled

Since the launchd module is used as the backend for the service module on macOS 10.4+, the enabled parameter cannot be changed, since the documentation for the same parameter in ansible.builtin.service states:

Whether the service should start on boot.

However, we also need a mechanism to enable or disable the service in general. I propose adding two new state actions: enabled/disabled, which would correspond to launchctl enabled/launchctl disabled, respectively. Note that these state actions will require a user ID, which will be obtained from the owner parameter (see below).

Eliminate the unloaded and reloaded states

Similar to the above suggestion, launchctl bootout should replace launchctl unload. Thus, the unload state should be deprecated and removed in a future release. As reloaded is essentially an alias for launchctl load or launchctl reload (depending on the service state), it should also be deprecated and removed.

Add a new required parameter, owner

The launchctl actions for enable/disable/bootstrap/bootout all require a numeric user ID. We'll need a new integer parameter for this, and in the spirit of Ansible conventions, I suggest calling it owner. We'll need to do some runtime checks to see if we get passed an integer or a string, and if the value is a string we'll need to do a UID lookup on the system via id -u <owner> and consequently, throw an error if the UID cannot be determined.

Compatibility concerns

From what I understand, the community.general collection requires Ansible 2.16+, which in turn requires macOS 10.15 (Catalina) or newer. I don't think that support for pre-10.11 hosts should be a concern.

Implementation

I propose the following plan to implement the above suggestions over the course of several releases:

  1. Future minor release(s):
    • The owner parameter is introduced to launchd. It is not required, but the documentation will state that it will be required in a future release. When owner is specified and state is started/stopped, then the launchd module will instead use launchctl bootstrap/launchctl bootout. Without owner, the old behavior is used but a deprecation warning will be printed.
    • The unloaded/reloaded states are considered deprecated. Using these states is still supported but a deprecation warning will be printed. Using either state with the new owner parameter will result in an error.
    • Introduce the new enabled/disabled states. Note that owner is required for these states.
  2. Future major release:
    • The owner parameter now becomes a required parameter.
    • Codepaths for the previous behavior of state: started/state stopped are removed and replaced with the new launchctl bootstrap/launchctl bootout ones.
    • The state actions for unloaded/reloaded are also removed.

For the first step, these actions can be spread across any number of minor releases. However, making owner mandatory and switching to the new behavior should be done in a single major release.

Issue Type

Feature Idea

Component Name

launchd

Code of Conduct

  • I agree to follow the Ansible Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureThis issue/PR relates to a feature requestmodulemodulepluginsplugin (any type)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions