Skip to content

Commit

Permalink
fixes saltstack#62446 ignore service state actions when in chroot
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholasmhughes committed Aug 9, 2022
1 parent b7dd4d1 commit 3a98e5d
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 6 deletions.
1 change: 1 addition & 0 deletions changelog/62446.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add ability to bypass service state actions and no-op while in chroot
120 changes: 114 additions & 6 deletions salt/states/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,18 @@ def _enabled_used_error(ret):
return ret


def _chroot_noop(ret):
"""
Take no action if running in chroot
"""
msg = "Running in chroot and chroot_ignore is True. Nothing to do."
if __opts__.get("test"):
log.info(msg)
ret["result"] = None
ret["comment"] = msg
return ret


def _enable(name, started, result=True, **kwargs):
"""
Enable the service
Expand Down Expand Up @@ -377,8 +389,12 @@ def _available(name, ret):
return avail


def running(name, enable=None, sig=None, init_delay=None, **kwargs):
def running(
name, enable=None, sig=None, init_delay=None, chroot_ignore=False, **kwargs
):
"""
.. versionchanged:: 3006.0
Ensure that the service is running
name
Expand All @@ -400,6 +416,16 @@ def running(name, enable=None, sig=None, init_delay=None, **kwargs):
for requisite states wherein a dependent state might assume a service
has started but is not yet fully initialized.
chroot_ignore : False
If set to ``True``, a check will be performed to determine if Salt is
running in a chroot environment using the ``virtual_subtype`` grain. If
that condition is also met, then this state will effectively become a
no-op state where no action is taken. This can be valuable behavior to
prevent wrapping multiple state blocks in templating to perform this
check.
.. versionadded:: 3006.0
no_block : False
**For systemd minions only.** Starts the service using ``--no-block``.
Expand Down Expand Up @@ -456,6 +482,10 @@ def running(name, enable=None, sig=None, init_delay=None, **kwargs):
if isinstance(enable, str):
enable = salt.utils.data.is_true(enable)

# Ignore all operations if chroot_ignore and virtual subtype is chroot
if chroot_ignore and "chroot" in __grains__.get("virtual_subtype", "").lower():
return _chroot_noop(ret)

if _offline():
ret["result"] = True
ret["comment"] = "Running in OFFLINE mode. Nothing to do"
Expand Down Expand Up @@ -607,8 +637,10 @@ def running(name, enable=None, sig=None, init_delay=None, **kwargs):
return ret


def dead(name, enable=None, sig=None, init_delay=None, **kwargs):
def dead(name, enable=None, sig=None, init_delay=None, chroot_ignore=False, **kwargs):
"""
.. versionchanged:: 3006.0
Ensure that the named service is dead by stopping the service if it is running
name
Expand All @@ -628,6 +660,16 @@ def dead(name, enable=None, sig=None, init_delay=None, **kwargs):
.. versionadded:: 2017.7.0
chroot_ignore : False
If set to ``True``, a check will be performed to determine if Salt is
running in a chroot environment using the ``virtual_subtype`` grain. If
that condition is also met, then this state will effectively become a
no-op state where no action is taken. This can be valuable behavior to
prevent wrapping multiple state blocks in templating to perform this
check.
.. versionadded:: 3006.0
no_block : False
**For systemd minions only.** Stops the service using ``--no-block``.
Expand Down Expand Up @@ -656,6 +698,10 @@ def dead(name, enable=None, sig=None, init_delay=None, **kwargs):
if isinstance(enable, str):
enable = salt.utils.data.is_true(enable)

# Ignore all operations if chroot_ignore and virtual subtype is chroot
if chroot_ignore and "chroot" in __grains__.get("virtual_subtype", "").lower():
return _chroot_noop(ret)

if _offline():
ret["result"] = True
ret["comment"] = "Running in OFFLINE mode. Nothing to do"
Expand Down Expand Up @@ -768,21 +814,37 @@ def dead(name, enable=None, sig=None, init_delay=None, **kwargs):
return ret


def enabled(name, **kwargs):
def enabled(name, chroot_ignore=False, **kwargs):
"""
.. versionchanged:: 3006.0
Ensure that the service is enabled on boot, only use this state if you
don't want to manage the running process, remember that if you want to
enable a running service to use the enable: True option for the running
or dead function.
name
The name of the init or rc script used to manage the service
chroot_ignore : False
If set to ``True``, a check will be performed to determine if Salt is
running in a chroot environment using the ``virtual_subtype`` grain. If
that condition is also met, then this state will effectively become a
no-op state where no action is taken. This can be valuable behavior to
prevent wrapping multiple state blocks in templating to perform this
check.
.. versionadded:: 3006.0
"""
ret = {"name": name, "changes": {}, "result": True, "comment": ""}

# used to let execution modules know which service state is being run.
__context__["service.state"] = "enabled"

# Ignore all operations if chroot_ignore and virtual subtype is chroot
if chroot_ignore and "chroot" in __grains__.get("virtual_subtype", "").lower():
return _chroot_noop(ret)

ret.update(_enable(name, None, **kwargs))
if __opts__.get("test") and ret.get(
"comment"
Expand All @@ -795,28 +857,45 @@ def enabled(name, **kwargs):
return ret


def disabled(name, **kwargs):
def disabled(name, chroot_ignore=False, **kwargs):
"""
.. versionchanged:: 3006.0
Ensure that the service is disabled on boot, only use this state if you
don't want to manage the running process, remember that if you want to
disable a service to use the enable: False option for the running or dead
function.
name
The name of the init or rc script used to manage the service
chroot_ignore : False
If set to ``True``, a check will be performed to determine if Salt is
running in a chroot environment using the ``virtual_subtype`` grain. If
that condition is also met, then this state will effectively become a
no-op state where no action is taken. This can be valuable behavior to
prevent wrapping multiple state blocks in templating to perform this
check.
.. versionadded:: 3006.0
"""
ret = {"name": name, "changes": {}, "result": True, "comment": ""}

# used to let execution modules know which service state is being run.
__context__["service.state"] = "disabled"

# Ignore all operations if chroot_ignore and virtual subtype is chroot
if chroot_ignore and "chroot" in __grains__.get("virtual_subtype", "").lower():
return _chroot_noop(ret)

ret.update(_disable(name, None, **kwargs))
return ret


def masked(name, runtime=False):
def masked(name, runtime=False, chroot_ignore=False):
"""
.. versionadded:: 2017.7.0
.. versionchanged:: 3006.0
.. note::
This state is only available on minions which use systemd_.
Expand Down Expand Up @@ -856,9 +935,23 @@ def masked(name, runtime=False):
.. _systemd: https://freedesktop.org/wiki/Software/systemd/
chroot_ignore : False
If set to ``True``, a check will be performed to determine if Salt is
running in a chroot environment using the ``virtual_subtype`` grain. If
that condition is also met, then this state will effectively become a
no-op state where no action is taken. This can be valuable behavior to
prevent wrapping multiple state blocks in templating to perform this
check.
.. versionadded:: 3006.0
"""
ret = {"name": name, "changes": {}, "result": True, "comment": ""}

# Ignore all operations if chroot_ignore and virtual subtype is chroot
if chroot_ignore and "chroot" in __grains__.get("virtual_subtype", "").lower():
return _chroot_noop(ret)

if "service.masked" not in __salt__:
ret["comment"] = "Service masking not available on this minion"
ret["result"] = False
Expand Down Expand Up @@ -896,9 +989,10 @@ def masked(name, runtime=False):
return ret


def unmasked(name, runtime=False):
def unmasked(name, runtime=False, chroot_ignore=False):
"""
.. versionadded:: 2017.7.0
.. versionchanged:: 3006.0
.. note::
This state is only available on minions which use systemd_.
Expand All @@ -922,9 +1016,23 @@ def unmasked(name, runtime=False):
.. _systemd: https://freedesktop.org/wiki/Software/systemd/
chroot_ignore : False
If set to ``True``, a check will be performed to determine if Salt is
running in a chroot environment using the ``virtual_subtype`` grain. If
that condition is also met, then this state will effectively become a
no-op state where no action is taken. This can be valuable behavior to
prevent wrapping multiple state blocks in templating to perform this
check.
.. versionadded:: 3006.0
"""
ret = {"name": name, "changes": {}, "result": True, "comment": ""}

# Ignore all operations if chroot_ignore and virtual subtype is chroot
if chroot_ignore and "chroot" in __grains__.get("virtual_subtype", "").lower():
return _chroot_noop(ret)

if "service.masked" not in __salt__:
ret["comment"] = "Service masking not available on this minion"
ret["result"] = False
Expand Down
15 changes: 15 additions & 0 deletions tests/pytests/unit/states/test_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def configure_loader_modules():
"__low__": {},
"__utils__": {},
"__context__": {},
"__grains__": {},
},
beaconstate: {"__salt__": {}, "__opts__": {}},
beaconmod: {"__salt__": {}, "__opts__": {}},
Expand Down Expand Up @@ -744,3 +745,17 @@ def test_running_with_reload():
finally:
if post_srv_disable:
modules["service.disable"](service_name)


@pytest.mark.parametrize(
"action", ["running", "dead", "disabled", "enabled", "masked", "unmasked"]
)
def test_chroot_ignore(action):
func = getattr(service, action)
with patch.dict(service.__grains__, {"virtual_subtype": "chroot"}):
ret = func("salt", chroot_ignore=True)
assert ret["result"] is None
assert (
ret["comment"]
== "Running in chroot and chroot_ignore is True. Nothing to do."
)

0 comments on commit 3a98e5d

Please sign in to comment.