Source code for saltext.salt_describe.runners.salt_describe_cron

# Copyright 2023 VMware, Inc.
# SPDX-License-Identifier: Apache-2.0
"""
Module for building state file

.. versionadded:: 3006

"""
import logging
import sys

import yaml
from saltext.salt_describe.utils.init import generate_files
from saltext.salt_describe.utils.init import parse_salt_ret
from saltext.salt_describe.utils.init import ret_info

__virtualname__ = "describe"


log = logging.getLogger(__name__)


def __virtual__():
    return __virtualname__


def _parse_pre_cron(line, user, commented_cron_job=False):
    if line.startswith("#"):
        try:
            return _parse_pre_cron(line.lstrip("#").lstrip(), user, commented_cron_job=True)
        except Exception:  # pylint: disable-broad-except
            log.debug("Failed to parse commented line as cron in pre: %s", line)
            return "comment", None, line
    if line.startswith("@"):
        # Its a "special" line
        data = []
        comps = line.split()
        if len(comps) < 2:
            # Invalid line
            log.debug("Invalid special line, skipping: %s", line)
            return "unknown", line
        cmd = " ".join(comps[1:])
        data = [
            {"special": comps[0]},
            {"comment": None},
            {"commented": commented_cron_job},
            {"identifier": False},
            {"user": user},
        ]
        return "special", cmd, data
    elif line.find("=") > 0 and (" " not in line or line.index("=") < line.index(" ")):
        # Appears to be a ENV setup line
        if not commented_cron_job:
            comps = line.split("=", 1)
            name = comps[0]
            data = [{"value": comps[1]}, {"user": user}]
            return "env", name, data
    elif len(line.split(" ")) > 5:
        # Appears to be a standard cron line
        comps = line.split(" ")
        cmd = " ".join(comps[5:])
        data = [
            {"minute": comps[0]},
            {"hour": comps[1]},
            {"daymonth": comps[2]},
            {"month": comps[3]},
            {"dayweek": comps[4]},
            {"comment": None},
            {"identifier": False},
            {"commented": commented_cron_job},
            {"user": user},
        ]
        return "cron", cmd, data

    return "unknown", None, line


[docs]def cron(tgt, user="root", include_pre=True, tgt_type="glob", config_system="salt"): """ Generate the state file for a user's cron data CLI Example: .. code-block:: bash salt-run describe.all minion-tgt user """ mod_name = sys._getframe().f_code.co_name log.info("Attempting to generate SLS file for %s", mod_name) cron_contents = __salt__["salt.execute"]( tgt, "cron.ls", arg=[user], tgt_type=tgt_type, ) sls_files = [] if not parse_salt_ret(ret=cron_contents, tgt=tgt): return ret_info(sls_files, mod=mod_name) for minion in list(cron_contents.keys()): minion_crons = cron_contents[minion] crons = minion_crons.get("crons", []) env = minion_crons.get("env", []) pre = minion_crons.get("pre", []) special = minion_crons.get("special", []) env_sls = {} for env_var in env: name = env_var["name"] value = env_var["value"] # Generate env state env_state = { "cron.env_present": [ {"value": value}, {"user": user}, ], } env_sls[name] = env_state crons_sls = {} for job in crons: # Generate cron state cron_state_name = job["cmd"] comment = job["comment"] if job["comment"] else None cron_state = { "cron.present": [ {"user": user}, {"minute": job["minute"]}, {"hour": job["hour"]}, {"daymonth": job["daymonth"]}, {"month": job["month"]}, {"dayweek": job["dayweek"]}, {"comment": comment}, {"commented": job["commented"]}, {"identifier": job["identifier"]}, ], } crons_sls[cron_state_name] = cron_state specials_sls = {} for job in special: # Generate special state special_state_name = job["cmd"] comment = job["comment"] if job["comment"] else None special_state = { "cron.present": [ {"user": user}, {"comment": comment}, {"commented": job["commented"]}, {"identifier": job["identifier"]}, {"special": job["spec"]}, ], } specials_sls[special_state_name] = special_state if include_pre: # do some parsing of `pre` into salt-able cron jobs for line in pre: line = line.lstrip() if line: entry_type, name, data = _parse_pre_cron(line, user) if entry_type == "comment": log.debug("Disregarding comment in cron parsing: %s", data) if entry_type == "env": env_sls[name] = {"cron.env_present": data} if entry_type == "cron": crons_sls[name] = {"cron.present": data} if entry_type == "special": specials_sls[name] = {"cron.present": data} # Merge them all together final_sls = {} for sls_contents in (env_sls, crons_sls, specials_sls): for state_name in sls_contents: final_sls[state_name] = sls_contents[state_name] sls_yaml = yaml.dump(final_sls) sls_files.append( generate_files(__opts__, minion, sls_yaml, sls_name="cron", config_system=config_system) ) return ret_info(sls_files, mod=mod_name)