From 22d7145d4fb33149d5e7e078d334207d0938d1f3 Mon Sep 17 00:00:00 2001 From: ScriptAutomate Date: Tue, 18 Jul 2023 15:40:22 -0500 Subject: [PATCH 01/46] Update Slack invite link and VMware Aria ref --- .github/config.yml | 4 ++-- CONTRIBUTING.rst | 2 +- README.rst | 9 +++++---- SUPPORT.rst | 2 +- doc/conf.py | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/config.yml b/.github/config.yml index 633569da991..94b18535bce 100644 --- a/.github/config.yml +++ b/.github/config.yml @@ -13,7 +13,7 @@ newIssueWelcomeComment: > - [Community Wiki](https://github.com/saltstack/community/wiki) - [Salt’s Contributor Guide](https://docs.saltproject.io/en/master/topics/development/contributing.html) - - [Join our Community Slack](https://join.slack.com/t/saltstackcommunity/shared_invite/zt-3av8jjyf-oBQ2M0vhXOhJpNpRkPWBvg) + - [Join our Community Slack](https://join.slack.com/t/saltstackcommunity/shared_invite/zt-1zlfxffs1-NuEH~G9TzOeuNGdsfZIl3w) - [IRC on LiberaChat](https://web.libera.chat/#salt) - [Salt Project YouTube channel](https://www.youtube.com/channel/UCpveTIucFx9ljGelW63-BWg) - [Salt Project Twitch channel](https://www.twitch.tv/saltprojectoss) @@ -39,7 +39,7 @@ newPRWelcomeComment: > - [Community Wiki](https://github.com/saltstack/community/wiki) - [Salt’s Contributor Guide](https://docs.saltproject.io/en/master/topics/development/contributing.html) - - [Join our Community Slack](https://join.slack.com/t/saltstackcommunity/shared_invite/zt-3av8jjyf-oBQ2M0vhXOhJpNpRkPWBvg) + - [Join our Community Slack](https://join.slack.com/t/saltstackcommunity/shared_invite/zt-1zlfxffs1-NuEH~G9TzOeuNGdsfZIl3w) - [IRC on LiberaChat](https://web.libera.chat/#salt) - [Salt Project YouTube channel](https://www.youtube.com/channel/UCpveTIucFx9ljGelW63-BWg) - [Salt Project Twitch channel](https://www.twitch.tv/saltprojectoss) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 5903a856723..80d03514945 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -8,7 +8,7 @@ in a number of ways: - Use Salt and open well-written bug reports. - Join a `working group `__. - Answer questions on `irc `__, - the `community Slack `__, + the `community Slack `__, the `salt-users mailing list `__, `Server Fault `__, diff --git a/README.rst b/README.rst index f5121f1a74d..6673d59ce9a 100644 --- a/README.rst +++ b/README.rst @@ -12,7 +12,7 @@ .. image:: https://img.shields.io/badge/slack-@saltstackcommunity-blue.svg?logo=slack :alt: Salt Project Slack Community - :target: https://join.slack.com/t/saltstackcommunity/shared_invite/zt-3av8jjyf-oBQ2M0vhXOhJpNpRkPWBvg + :target: https://join.slack.com/t/saltstackcommunity/shared_invite/zt-1zlfxffs1-NuEH~G9TzOeuNGdsfZIl3w .. image:: https://img.shields.io/twitch/status/saltprojectoss :alt: Salt Project Twitch Channel @@ -71,7 +71,8 @@ In addition to configuration management Salt can also: About our sponsors ================== -Salt powers VMware's `vRealize Automation SaltStack Config`_, and can be found +Salt powers VMware's `VMware Aria Automation Config`_ +(previously vRealize Automation SaltStack Config / SaltStack Enterprise), and can be found under the hood of products from Juniper, Cisco, Cloudflare, Nutanix, SUSE, and Tieto, to name a few. @@ -179,8 +180,8 @@ used by external modules. A complete list of attributions and dependencies can be found here: `salt/DEPENDENCIES.md `_ -.. _Salt Project Community Slack: https://join.slack.com/t/saltstackcommunity/shared_invite/zt-3av8jjyf-oBQ2M0vhXOhJpNpRkPWBvg -.. _vRealize Automation SaltStack Config: https://www.vmware.com/products/vrealize-automation/saltstack-config.html +.. _Salt Project Community Slack: https://join.slack.com/t/saltstackcommunity/shared_invite/zt-1zlfxffs1-NuEH~G9TzOeuNGdsfZIl3w +.. _VMware Aria Automation Config: https://www.vmware.com/products/vrealize-automation/saltstack-config.html .. _Latest Salt Documentation: https://docs.saltproject.io/en/latest/ .. _Open an issue: https://github.com/saltstack/salt/issues/new/choose .. _SECURITY.md: https://github.com/saltstack/salt/blob/master/SECURITY.md diff --git a/SUPPORT.rst b/SUPPORT.rst index bfe9d1cbeae..d74336a5ab0 100644 --- a/SUPPORT.rst +++ b/SUPPORT.rst @@ -11,7 +11,7 @@ it may take a few moments for someone to reply. **SaltStack Slack** - Alongside IRC is our SaltStack Community Slack for the SaltStack Working groups. Use the following link to request an invitation. -``_ +``_ **Mailing List** - The SaltStack community users mailing list is hosted by Google groups. Anyone can post to ask questions about SaltStack products and diff --git a/doc/conf.py b/doc/conf.py index 653d912c20d..2a0b6d1125d 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -174,7 +174,7 @@ rst_prolog = """\ .. _`salt-users`: https://groups.google.com/forum/#!forum/salt-users .. _`salt-announce`: https://groups.google.com/forum/#!forum/salt-announce .. _`salt-packagers`: https://groups.google.com/forum/#!forum/salt-packagers -.. _`salt-slack`: https://join.slack.com/t/saltstackcommunity/shared_invite/zt-3av8jjyf-oBQ2M0vhXOhJpNpRkPWBvg +.. _`salt-slack`: https://join.slack.com/t/saltstackcommunity/shared_invite/zt-1zlfxffs1-NuEH~G9TzOeuNGdsfZIl3w .. |windownload| raw:: html

Python3 x86: Date: Mon, 17 Jul 2023 16:59:43 -0400 Subject: [PATCH 02/46] Add `tools vm list` command --- tools/vm.py | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tools/vm.py b/tools/vm.py index f7b2837ae1b..a52281f74df 100644 --- a/tools/vm.py +++ b/tools/vm.py @@ -563,6 +563,60 @@ def download_artifacts(ctx: Context, name: str): vm.download_artifacts() +@vm.command( + name="list", + arguments={ + "key_name": {"help": "The SSH key name."}, + }, +) +def list_vms( + ctx: Context, + key_name: str = os.environ.get("RUNNER_NAME"), # type: ignore[assignment] +): + """ + List the vms associated with the given key. + """ + if key_name is None: + ctx.exit(1, "We need a key name to filter the instances by.") + ec2 = boto3.resource("ec2", region_name=ctx.parser.options.region) + # First let's get the instances on AWS associated with the key given + filters = [ + {"Name": "key-name", "Values": [key_name]}, + ] + try: + instances = list( + ec2.instances.filter( + Filters=filters, + ) + ) + except ClientError as exc: + if "RequestExpired" not in str(exc): + raise + ctx.error(str(exc)) + ctx.exit(1) + + for instance in instances: + state = instance.state["Name"] + ip_addr = instance.public_ip_address + ami = instance.image_id + vm_name = None + for tag in instance.tags: + if tag.get("Key") == "vm-name": + vm_name = tag.get("Value") + break + + if vm_name is not None: + sep = "\n " + extra_info = { + "IP": ip_addr, + "AMI": ami, + } + extras = sep + sep.join( + [f"{key}: {value}" for key, value in extra_info.items()] + ) + log.info(f"{vm_name} ({state}){extras}") + + @attr.s(frozen=True, kw_only=True) class AMIConfig: ami: str = attr.ib() From 6d5e8ce8874a33131505270315a851587ba7cf2c Mon Sep 17 00:00:00 2001 From: MKLeb Date: Mon, 17 Jul 2023 17:28:56 -0400 Subject: [PATCH 03/46] Add states filtering --- tools/vm.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/vm.py b/tools/vm.py index a52281f74df..6e620e37bea 100644 --- a/tools/vm.py +++ b/tools/vm.py @@ -567,11 +567,17 @@ def download_artifacts(ctx: Context, name: str): name="list", arguments={ "key_name": {"help": "The SSH key name."}, + "states": { + "help": "The instance state to filter by.", + "flags": ["-s", "-state"], + "action": "append", + }, }, ) def list_vms( ctx: Context, key_name: str = os.environ.get("RUNNER_NAME"), # type: ignore[assignment] + states: set[str] = None, ): """ List the vms associated with the given key. @@ -596,7 +602,10 @@ def list_vms( ctx.exit(1) for instance in instances: - state = instance.state["Name"] + vm_state = instance.state["Name"] + # Filter by wanted states + if states and vm_state not in states: + continue ip_addr = instance.public_ip_address ami = instance.image_id vm_name = None @@ -614,7 +623,7 @@ def list_vms( extras = sep + sep.join( [f"{key}: {value}" for key, value in extra_info.items()] ) - log.info(f"{vm_name} ({state}){extras}") + log.info(f"{vm_name} ({vm_state}){extras}") @attr.s(frozen=True, kw_only=True) From 86719a68b5f9c67957a3272a259dfe08e2aa0ae4 Mon Sep 17 00:00:00 2001 From: MKLeb Date: Tue, 18 Jul 2023 15:11:18 -0400 Subject: [PATCH 04/46] Add sync-cache command to make the stored state of the machine match up to what ec2 has for all running machines --- tools/vm.py | 99 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 78 insertions(+), 21 deletions(-) diff --git a/tools/vm.py b/tools/vm.py index 6e620e37bea..ea1566fc74d 100644 --- a/tools/vm.py +++ b/tools/vm.py @@ -563,6 +563,52 @@ def download_artifacts(ctx: Context, name: str): vm.download_artifacts() +@vm.command( + name="sync-cache", + arguments={ + "key_name": {"help": "The SSH key name."}, + }, +) +def sync_cache( + ctx: Context, + key_name: str = os.environ.get("RUNNER_NAME"), # type: ignore[assignment] +): + """ + Sync the cache + """ + ec2_instances = _filter_instances_by_state( + _get_instances_by_key(ctx, key_name), + {"running"}, + ) + + cached_instances = {} + if STATE_DIR.exists(): + for state_path in STATE_DIR.iterdir(): + instance_id = (state_path / "instance-id").read_text() + cached_instances[instance_id] = state_path.name + + # Find what instances we are missing in our cached states + to_write = {} + to_remove = cached_instances.copy() + for instance in ec2_instances: + if instance.id not in cached_instances: + for tag in instance.tags: + if tag.get("Key") == "vm-name": + to_write[tag.get("Value")] = instance + break + else: + del to_remove[instance.id] + + for cached_id, vm_name in to_remove.items(): + shutil.rmtree(STATE_DIR / vm_name) + log.info(f"REMOVED {vm_name} ({cached_id}) from cache at {STATE_DIR / vm_name}") + + for name_tag, vm_instance in to_write.items(): + vm_write = VM(ctx=ctx, name=name_tag, region_name=ctx.parser.options.region) + vm_write.instance = vm_instance + vm_write.write_state() + + @vm.command( name="list", arguments={ @@ -582,30 +628,13 @@ def list_vms( """ List the vms associated with the given key. """ - if key_name is None: - ctx.exit(1, "We need a key name to filter the instances by.") - ec2 = boto3.resource("ec2", region_name=ctx.parser.options.region) - # First let's get the instances on AWS associated with the key given - filters = [ - {"Name": "key-name", "Values": [key_name]}, - ] - try: - instances = list( - ec2.instances.filter( - Filters=filters, - ) - ) - except ClientError as exc: - if "RequestExpired" not in str(exc): - raise - ctx.error(str(exc)) - ctx.exit(1) + instances = _filter_instances_by_state( + _get_instances_by_key(ctx, key_name), + states, + ) for instance in instances: vm_state = instance.state["Name"] - # Filter by wanted states - if states and vm_state not in states: - continue ip_addr = instance.public_ip_address ami = instance.image_id vm_name = None @@ -626,6 +655,34 @@ def list_vms( log.info(f"{vm_name} ({vm_state}){extras}") +def _get_instances_by_key(ctx: Context, key_name: str): + if key_name is None: + ctx.exit(1, "We need a key name to filter the instances by.") + ec2 = boto3.resource("ec2", region_name=ctx.parser.options.region) + # First let's get the instances on AWS associated with the key given + filters = [ + {"Name": "key-name", "Values": [key_name]}, + ] + try: + instances = list( + ec2.instances.filter( + Filters=filters, + ) + ) + except ClientError as exc: + if "RequestExpired" not in str(exc): + raise + ctx.error(str(exc)) + ctx.exit(1) + return instances + + +def _filter_instances_by_state(instances: list[Instance], states: set[str] | None): + if states is None: + return instances + return [instance for instance in instances if instance.state["Name"] in states] + + @attr.s(frozen=True, kw_only=True) class AMIConfig: ami: str = attr.ib() From 4e90e0e7fe94913e98ebb9806a35c88a5fb9776b Mon Sep 17 00:00:00 2001 From: MKLeb Date: Tue, 18 Jul 2023 15:41:56 -0400 Subject: [PATCH 05/46] Add `--delete` option to `tools vm sync-cache` to force the user to know that they are deleting cache entries that are no longer valid --- tools/vm.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tools/vm.py b/tools/vm.py index ea1566fc74d..ac03674cd68 100644 --- a/tools/vm.py +++ b/tools/vm.py @@ -567,11 +567,16 @@ def download_artifacts(ctx: Context, name: str): name="sync-cache", arguments={ "key_name": {"help": "The SSH key name."}, + "delete": { + "help": "Delete the entries in the cache that don't align with ec2", + "action": "store_true", + }, }, ) def sync_cache( ctx: Context, key_name: str = os.environ.get("RUNNER_NAME"), # type: ignore[assignment] + delete: bool = False, ): """ Sync the cache @@ -600,8 +605,17 @@ def sync_cache( del to_remove[instance.id] for cached_id, vm_name in to_remove.items(): - shutil.rmtree(STATE_DIR / vm_name) - log.info(f"REMOVED {vm_name} ({cached_id}) from cache at {STATE_DIR / vm_name}") + if delete: + shutil.rmtree(STATE_DIR / vm_name) + log.info( + f"REMOVED {vm_name} ({cached_id.strip()}) from cache at {STATE_DIR / vm_name}" + ) + else: + log.info( + f"Would remove {vm_name} ({cached_id.strip()}) from cache at {STATE_DIR / vm_name}" + ) + if not delete and to_remove: + log.info("To force the removal of the above cache entries, pass --delete") for name_tag, vm_instance in to_write.items(): vm_write = VM(ctx=ctx, name=name_tag, region_name=ctx.parser.options.region) From 9ea5365a47a6d716aee579e927f169fcf2028a06 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Tue, 18 Jul 2023 17:29:35 +0100 Subject: [PATCH 06/46] Remove unused variables Signed-off-by: Pedro Algarvio --- salt/auth/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/salt/auth/__init__.py b/salt/auth/__init__.py index 0a93e803229..df2eebe4f85 100644 --- a/salt/auth/__init__.py +++ b/salt/auth/__init__.py @@ -340,8 +340,6 @@ class LoadAuth: load["user"] == self.opts.get("user", "root") or load["user"] == "root" ): for check_key in key: - dgm_user = self.opts.get("user", "root") - dgm_check_key = key[check_key] if auth_key == key[check_key]: return True log.warning( From acb7a3344b878a19e1839cf7fdc1c9322139bd60 Mon Sep 17 00:00:00 2001 From: "Ryan Addessi (raddessi)" Date: Thu, 8 Jun 2023 16:33:00 -0600 Subject: [PATCH 07/46] fix: slack bolt engine name is slack_bolt (cherry picked from commit d05e5469a52737a4e3687620934525ead4179009) --- salt/engines/slack_bolt_engine.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/salt/engines/slack_bolt_engine.py b/salt/engines/slack_bolt_engine.py index 0a0417d160a..67fba0e6b05 100644 --- a/salt/engines/slack_bolt_engine.py +++ b/salt/engines/slack_bolt_engine.py @@ -111,7 +111,7 @@ the desired command. .. code-block:: text engines: - - slack: + - slack_bolt: app_token: "xapp-x-xxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" bot_token: 'xoxb-xxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx' control: True @@ -149,7 +149,7 @@ must be quoted, or else PyYAML will fail to load the configuration. .. code-block:: text engines: - - slack: + - slack_bolt: groups_pillar: slack_engine_pillar app_token: "xapp-x-xxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" bot_token: 'xoxb-xxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx' From 6f8f32e5e8746a39530f674c7758b321d6dde1dc Mon Sep 17 00:00:00 2001 From: "Ryan Addessi (raddessi)" Date: Fri, 9 Jun 2023 11:00:52 -0600 Subject: [PATCH 08/46] f-strings (cherry picked from commit b381f39024545842dd8a52bc724efb7712cef263) --- salt/engines/slack_bolt_engine.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/salt/engines/slack_bolt_engine.py b/salt/engines/slack_bolt_engine.py index 67fba0e6b05..75eb0909e48 100644 --- a/salt/engines/slack_bolt_engine.py +++ b/salt/engines/slack_bolt_engine.py @@ -234,7 +234,7 @@ class SlackClient: self.msg_queue = collections.deque() - trigger_pattern = "(^{}.*)".format(trigger_string) + trigger_pattern = f"(^{trigger_string}.*)" # Register message_trigger when we see messages that start # with the trigger string @@ -843,7 +843,7 @@ class SlackClient: results = {} for jid in outstanding_jids: # results[jid] = runner.cmd('jobs.lookup_jid', [jid]) - if self.master_minion.returners["{}.get_jid".format(source)](jid): + if self.master_minion.returners[f"{source}.get_jid"](jid): job_result = runner.cmd("jobs.list_job", [jid]) jid_result = job_result.get("Result", {}) jid_function = job_result.get("Function", {}) @@ -954,7 +954,7 @@ class SlackClient: ) ts = time.time() st = datetime.datetime.fromtimestamp(ts).strftime("%Y%m%d%H%M%S%f") - filename = "salt-results-{}.yaml".format(st) + filename = f"salt-results-{st}.yaml" resp = self.app.client.files_upload( channels=channel, filename=filename, @@ -1075,4 +1075,4 @@ def start( ) client.run_commands_from_slack_async(message_generator, fire_all, tag, control) except Exception: # pylint: disable=broad-except - raise Exception("{}".format(traceback.format_exc())) + raise Exception(f"{traceback.format_exc()}") From 006bf1f9cbfaa2dd08904951e67f5c0df852038f Mon Sep 17 00:00:00 2001 From: nicholasmhughes Date: Thu, 20 Apr 2023 14:52:40 -0400 Subject: [PATCH 09/46] fixes saltstack/salt#64122 state_queue type checking does not allow int values (cherry picked from commit 8f0f4f1d3bd912ad2a54c17ebdd4e486748a83e3) --- changelog/64122.fixed.md | 1 + salt/config/__init__.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog/64122.fixed.md diff --git a/changelog/64122.fixed.md b/changelog/64122.fixed.md new file mode 100644 index 00000000000..b9b0b026c94 --- /dev/null +++ b/changelog/64122.fixed.md @@ -0,0 +1 @@ +Fix state_queue type checking to allow int values diff --git a/salt/config/__init__.py b/salt/config/__init__.py index 16326634749..781c5637409 100644 --- a/salt/config/__init__.py +++ b/salt/config/__init__.py @@ -373,7 +373,7 @@ VALID_OPTS = immutabletypes.freeze( # applications that depend on the original format. "unique_jid": bool, # Governs whether state runs will queue or fail to run when a state is already running - "state_queue": bool, + "state_queue": (bool, int), # Tells the highstate outputter to show successful states. False will omit successes. "state_verbose": bool, # Specify the format for state outputs. See highstate outputter for additional details. From 6a6e1d3ec3ae26e21a64bf5fa5a77f24f77375a3 Mon Sep 17 00:00:00 2001 From: Twangboy Date: Mon, 1 May 2023 17:35:34 -0600 Subject: [PATCH 10/46] Write some tests (cherry picked from commit 962f708c92add21d132c74b6ca8ea968850d84f7) --- .../unit/config/test__validate_opts.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/pytests/unit/config/test__validate_opts.py b/tests/pytests/unit/config/test__validate_opts.py index 3359a55bd85..a9112efdef1 100644 --- a/tests/pytests/unit/config/test__validate_opts.py +++ b/tests/pytests/unit/config/test__validate_opts.py @@ -401,3 +401,26 @@ def test_dict_bool_none_types(option_value, expected): """ result = salt.config._validate_opts({"ssl": option_value}) assert result is expected + + +@pytest.mark.parametrize( + "option_value,expected", + [ + ([1, 2, 3], False), # list + ((1, 2, 3), False), # tuple + ({"key": "value"}, False), # dict + ("str", False), # str + (True, True), # bool + (1, True), # int + (0.123, False), # float + (None, False), # None + ], +) +def test_bool_int_types(option_value, expected): + """ + Some config settings have three types, dict, bool, and None which should + evaluate as True. All others should return False. + ssl is a dict, bool type config option + """ + result = salt.config._validate_opts({"state_queue": option_value}) + assert result is expected From f2f19771a3d5ccfcf7dc483dd3c92810e51dc5d3 Mon Sep 17 00:00:00 2001 From: Twangboy Date: Mon, 1 May 2023 17:38:55 -0600 Subject: [PATCH 11/46] Fix test description (cherry picked from commit afcd6a8114a0cb2301b325c4bfc60406f640f94b) --- tests/pytests/unit/config/test__validate_opts.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/pytests/unit/config/test__validate_opts.py b/tests/pytests/unit/config/test__validate_opts.py index a9112efdef1..741631e6f81 100644 --- a/tests/pytests/unit/config/test__validate_opts.py +++ b/tests/pytests/unit/config/test__validate_opts.py @@ -418,9 +418,9 @@ def test_dict_bool_none_types(option_value, expected): ) def test_bool_int_types(option_value, expected): """ - Some config settings have three types, dict, bool, and None which should - evaluate as True. All others should return False. - ssl is a dict, bool type config option + Some config settings have two types, bool and int. In that case, bool and + int should evaluate as True. All others should return False. + state_queue is a bool/int config option """ result = salt.config._validate_opts({"state_queue": option_value}) assert result is expected From 1de8d1b18ba6626d0c2dd62496559b0b074856da Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Tue, 14 Mar 2023 15:15:14 -0400 Subject: [PATCH 12/46] Update `py` renderer documentation with information on user-provided context Update the `py` renderer's documentation to include information on how user-provided context data is typically presented. (cherry picked from commit e8e033a8f7303135c3a25780caf232d4d7fa4858) --- salt/renderers/py.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/salt/renderers/py.py b/salt/renderers/py.py index 0f67d7e62e7..2b102e2ec87 100644 --- a/salt/renderers/py.py +++ b/salt/renderers/py.py @@ -46,8 +46,23 @@ execution functions, grains, pillar, etc. They are: ``/srv/salt/foo/bar/baz.sls``, then ``__sls__`` in that file will be ``foo.bar.baz``. -When writing a reactor SLS file the global context ``data`` (same as context ``{{ data }}`` -for states written with Jinja + YAML) is available. The following YAML + Jinja state declaration: +When used in a scenario where additional user-provided context data is supplied +(such as with :mod:`file.managed `), the additional +data will typically be injected into the script as one or more global +variables: + +.. code-block:: jinja + /etc/http/conf/http.conf: + file.managed: + - source: salt://apache/generate_http_conf.py + - template: py + - context: + # Will be injected as the global variable "site_name". + site_name: {{ site_name }} + +When writing a reactor SLS file the global context ``data`` (same as context +``{{ data }}`` for states written with Jinja + YAML) is available. The +following YAML + Jinja state declaration: .. code-block:: jinja From 9b8f810f88afd7bbd49aa14c20e8560a156a36de Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Mon, 24 Apr 2023 19:28:13 +0100 Subject: [PATCH 13/46] Formatting fix Signed-off-by: Pedro Algarvio (cherry picked from commit 5a7854908fb7095ad08cfbfe314a29f121ffab5d) --- salt/renderers/py.py | 1 + 1 file changed, 1 insertion(+) diff --git a/salt/renderers/py.py b/salt/renderers/py.py index 2b102e2ec87..3ce58ac405c 100644 --- a/salt/renderers/py.py +++ b/salt/renderers/py.py @@ -52,6 +52,7 @@ data will typically be injected into the script as one or more global variables: .. code-block:: jinja + /etc/http/conf/http.conf: file.managed: - source: salt://apache/generate_http_conf.py From 37d4acebd5e265d24f3c9d6698b769935eff3f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Mon, 26 Jun 2023 13:23:28 +0100 Subject: [PATCH 14/46] Fix detection of Salt codename by salt_version module (cherry picked from commit e6abf4b2d5285a9ef5d98d9eeb80947da82be2df) --- salt/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/version.py b/salt/version.py index 43cb5f86f75..7d608fd14d9 100644 --- a/salt/version.py +++ b/salt/version.py @@ -78,7 +78,7 @@ class SaltVersionsInfo(type): ALUMINIUM = SaltVersion("Aluminium" , info=3003, released=True) SILICON = SaltVersion("Silicon" , info=3004, released=True) PHOSPHORUS = SaltVersion("Phosphorus" , info=3005, released=True) - SULFUR = SaltVersion("Sulfur" , info=(3006, 0), released=True) + SULFUR = SaltVersion("Sulfur" , info=3006, released=True) CHLORINE = SaltVersion("Chlorine" , info=(3007, 0)) ARGON = SaltVersion("Argon" , info=(3008, 0)) POTASSIUM = SaltVersion("Potassium" , info=(3009, 0)) From d14f3becb5863ce740ce76b908cce9686844a9d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Tue, 27 Jun 2023 11:59:06 +0100 Subject: [PATCH 15/46] Fix mess with version detection bad version definition (cherry picked from commit f5861ccb10bbe602f052a5f0d1da58b52f271b91) --- salt/version.py | 208 ++++++++++++++++++++++++------------------------ 1 file changed, 103 insertions(+), 105 deletions(-) diff --git a/salt/version.py b/salt/version.py index 7d608fd14d9..22ba1905c4b 100644 --- a/salt/version.py +++ b/salt/version.py @@ -79,108 +79,108 @@ class SaltVersionsInfo(type): SILICON = SaltVersion("Silicon" , info=3004, released=True) PHOSPHORUS = SaltVersion("Phosphorus" , info=3005, released=True) SULFUR = SaltVersion("Sulfur" , info=3006, released=True) - CHLORINE = SaltVersion("Chlorine" , info=(3007, 0)) - ARGON = SaltVersion("Argon" , info=(3008, 0)) - POTASSIUM = SaltVersion("Potassium" , info=(3009, 0)) - CALCIUM = SaltVersion("Calcium" , info=(3010, 0)) - SCANDIUM = SaltVersion("Scandium" , info=(3011, 0)) - TITANIUM = SaltVersion("Titanium" , info=(3012, 0)) - VANADIUM = SaltVersion("Vanadium" , info=(3013, 0)) - CHROMIUM = SaltVersion("Chromium" , info=(3014, 0)) - MANGANESE = SaltVersion("Manganese" , info=(3015, 0)) - IRON = SaltVersion("Iron" , info=(3016, 0)) - COBALT = SaltVersion("Cobalt" , info=(3017, 0)) - NICKEL = SaltVersion("Nickel" , info=(3018, 0)) - COPPER = SaltVersion("Copper" , info=(3019, 0)) - ZINC = SaltVersion("Zinc" , info=(3020, 0)) - GALLIUM = SaltVersion("Gallium" , info=(3021, 0)) - GERMANIUM = SaltVersion("Germanium" , info=(3022, 0)) - ARSENIC = SaltVersion("Arsenic" , info=(3023, 0)) - SELENIUM = SaltVersion("Selenium" , info=(3024, 0)) - BROMINE = SaltVersion("Bromine" , info=(3025, 0)) - KRYPTON = SaltVersion("Krypton" , info=(3026, 0)) - RUBIDIUM = SaltVersion("Rubidium" , info=(3027, 0)) - STRONTIUM = SaltVersion("Strontium" , info=(3028, 0)) - YTTRIUM = SaltVersion("Yttrium" , info=(3029, 0)) - ZIRCONIUM = SaltVersion("Zirconium" , info=(3030, 0)) - NIOBIUM = SaltVersion("Niobium" , info=(3031, 0)) - MOLYBDENUM = SaltVersion("Molybdenum" , info=(3032, 0)) - TECHNETIUM = SaltVersion("Technetium" , info=(3033, 0)) - RUTHENIUM = SaltVersion("Ruthenium" , info=(3034, 0)) - RHODIUM = SaltVersion("Rhodium" , info=(3035, 0)) - PALLADIUM = SaltVersion("Palladium" , info=(3036, 0)) - SILVER = SaltVersion("Silver" , info=(3037, 0)) - CADMIUM = SaltVersion("Cadmium" , info=(3038, 0)) - INDIUM = SaltVersion("Indium" , info=(3039, 0)) - TIN = SaltVersion("Tin" , info=(3040, 0)) - ANTIMONY = SaltVersion("Antimony" , info=(3041, 0)) - TELLURIUM = SaltVersion("Tellurium" , info=(3042, 0)) - IODINE = SaltVersion("Iodine" , info=(3043, 0)) - XENON = SaltVersion("Xenon" , info=(3044, 0)) - CESIUM = SaltVersion("Cesium" , info=(3045, 0)) - BARIUM = SaltVersion("Barium" , info=(3046, 0)) - LANTHANUM = SaltVersion("Lanthanum" , info=(3047, 0)) - CERIUM = SaltVersion("Cerium" , info=(3048, 0)) - PRASEODYMIUM = SaltVersion("Praseodymium" , info=(3049, 0)) - NEODYMIUM = SaltVersion("Neodymium" , info=(3050, 0)) - PROMETHIUM = SaltVersion("Promethium" , info=(3051, 0)) - SAMARIUM = SaltVersion("Samarium" , info=(3052, 0)) - EUROPIUM = SaltVersion("Europium" , info=(3053, 0)) - GADOLINIUM = SaltVersion("Gadolinium" , info=(3054, 0)) - TERBIUM = SaltVersion("Terbium" , info=(3055, 0)) - DYSPROSIUM = SaltVersion("Dysprosium" , info=(3056, 0)) - HOLMIUM = SaltVersion("Holmium" , info=(3057, 0)) - ERBIUM = SaltVersion("Erbium" , info=(3058, 0)) - THULIUM = SaltVersion("Thulium" , info=(3059, 0)) - YTTERBIUM = SaltVersion("Ytterbium" , info=(3060, 0)) - LUTETIUM = SaltVersion("Lutetium" , info=(3061, 0)) - HAFNIUM = SaltVersion("Hafnium" , info=(3062, 0)) - TANTALUM = SaltVersion("Tantalum" , info=(3063, 0)) - TUNGSTEN = SaltVersion("Tungsten" , info=(3064, 0)) - RHENIUM = SaltVersion("Rhenium" , info=(3065, 0)) - OSMIUM = SaltVersion("Osmium" , info=(3066, 0)) - IRIDIUM = SaltVersion("Iridium" , info=(3067, 0)) - PLATINUM = SaltVersion("Platinum" , info=(3068, 0)) - GOLD = SaltVersion("Gold" , info=(3069, 0)) - MERCURY = SaltVersion("Mercury" , info=(3070, 0)) - THALLIUM = SaltVersion("Thallium" , info=(3071, 0)) - LEAD = SaltVersion("Lead" , info=(3072, 0)) - BISMUTH = SaltVersion("Bismuth" , info=(3073, 0)) - POLONIUM = SaltVersion("Polonium" , info=(3074, 0)) - ASTATINE = SaltVersion("Astatine" , info=(3075, 0)) - RADON = SaltVersion("Radon" , info=(3076, 0)) - FRANCIUM = SaltVersion("Francium" , info=(3077, 0)) - RADIUM = SaltVersion("Radium" , info=(3078, 0)) - ACTINIUM = SaltVersion("Actinium" , info=(3079, 0)) - THORIUM = SaltVersion("Thorium" , info=(3080, 0)) - PROTACTINIUM = SaltVersion("Protactinium" , info=(3081, 0)) - URANIUM = SaltVersion("Uranium" , info=(3082, 0)) - NEPTUNIUM = SaltVersion("Neptunium" , info=(3083, 0)) - PLUTONIUM = SaltVersion("Plutonium" , info=(3084, 0)) - AMERICIUM = SaltVersion("Americium" , info=(3085, 0)) - CURIUM = SaltVersion("Curium" , info=(3086, 0)) - BERKELIUM = SaltVersion("Berkelium" , info=(3087, 0)) - CALIFORNIUM = SaltVersion("Californium" , info=(3088, 0)) - EINSTEINIUM = SaltVersion("Einsteinium" , info=(3089, 0)) - FERMIUM = SaltVersion("Fermium" , info=(3090, 0)) - MENDELEVIUM = SaltVersion("Mendelevium" , info=(3091, 0)) - NOBELIUM = SaltVersion("Nobelium" , info=(3092, 0)) - LAWRENCIUM = SaltVersion("Lawrencium" , info=(3093, 0)) - RUTHERFORDIUM = SaltVersion("Rutherfordium", info=(3094, 0)) - DUBNIUM = SaltVersion("Dubnium" , info=(3095, 0)) - SEABORGIUM = SaltVersion("Seaborgium" , info=(3096, 0)) - BOHRIUM = SaltVersion("Bohrium" , info=(3097, 0)) - HASSIUM = SaltVersion("Hassium" , info=(3098, 0)) - MEITNERIUM = SaltVersion("Meitnerium" , info=(3099, 0)) - DARMSTADTIUM = SaltVersion("Darmstadtium" , info=(3100, 0)) - ROENTGENIUM = SaltVersion("Roentgenium" , info=(3101, 0)) - COPERNICIUM = SaltVersion("Copernicium" , info=(3102, 0)) - NIHONIUM = SaltVersion("Nihonium" , info=(3103, 0)) - FLEROVIUM = SaltVersion("Flerovium" , info=(3104, 0)) - MOSCOVIUM = SaltVersion("Moscovium" , info=(3105, 0)) - LIVERMORIUM = SaltVersion("Livermorium" , info=(3106, 0)) - TENNESSINE = SaltVersion("Tennessine" , info=(3107, 0)) - OGANESSON = SaltVersion("Oganesson" , info=(3108, 0)) + CHLORINE = SaltVersion("Chlorine" , info=3007) + ARGON = SaltVersion("Argon" , info=3008) + POTASSIUM = SaltVersion("Potassium" , info=3009) + CALCIUM = SaltVersion("Calcium" , info=3010) + SCANDIUM = SaltVersion("Scandium" , info=3011) + TITANIUM = SaltVersion("Titanium" , info=3012) + VANADIUM = SaltVersion("Vanadium" , info=3013) + CHROMIUM = SaltVersion("Chromium" , info=3014) + MANGANESE = SaltVersion("Manganese" , info=3015) + IRON = SaltVersion("Iron" , info=3016) + COBALT = SaltVersion("Cobalt" , info=3017) + NICKEL = SaltVersion("Nickel" , info=3018) + COPPER = SaltVersion("Copper" , info=3019) + ZINC = SaltVersion("Zinc" , info=3020) + GALLIUM = SaltVersion("Gallium" , info=3021) + GERMANIUM = SaltVersion("Germanium" , info=3022) + ARSENIC = SaltVersion("Arsenic" , info=3023) + SELENIUM = SaltVersion("Selenium" , info=3024) + BROMINE = SaltVersion("Bromine" , info=3025) + KRYPTON = SaltVersion("Krypton" , info=3026) + RUBIDIUM = SaltVersion("Rubidium" , info=3027) + STRONTIUM = SaltVersion("Strontium" , info=3028) + YTTRIUM = SaltVersion("Yttrium" , info=3029) + ZIRCONIUM = SaltVersion("Zirconium" , info=3030) + NIOBIUM = SaltVersion("Niobium" , info=3031) + MOLYBDENUM = SaltVersion("Molybdenum" , info=3032) + TECHNETIUM = SaltVersion("Technetium" , info=3033) + RUTHENIUM = SaltVersion("Ruthenium" , info=3034) + RHODIUM = SaltVersion("Rhodium" , info=3035) + PALLADIUM = SaltVersion("Palladium" , info=3036) + SILVER = SaltVersion("Silver" , info=3037) + CADMIUM = SaltVersion("Cadmium" , info=3038) + INDIUM = SaltVersion("Indium" , info=3039) + TIN = SaltVersion("Tin" , info=3040) + ANTIMONY = SaltVersion("Antimony" , info=3041) + TELLURIUM = SaltVersion("Tellurium" , info=3042) + IODINE = SaltVersion("Iodine" , info=3043) + XENON = SaltVersion("Xenon" , info=3044) + CESIUM = SaltVersion("Cesium" , info=3045) + BARIUM = SaltVersion("Barium" , info=3046) + LANTHANUM = SaltVersion("Lanthanum" , info=3047) + CERIUM = SaltVersion("Cerium" , info=3048) + PRASEODYMIUM = SaltVersion("Praseodymium" , info=3049) + NEODYMIUM = SaltVersion("Neodymium" , info=3050) + PROMETHIUM = SaltVersion("Promethium" , info=3051) + SAMARIUM = SaltVersion("Samarium" , info=3052) + EUROPIUM = SaltVersion("Europium" , info=3053) + GADOLINIUM = SaltVersion("Gadolinium" , info=3054) + TERBIUM = SaltVersion("Terbium" , info=3055) + DYSPROSIUM = SaltVersion("Dysprosium" , info=3056) + HOLMIUM = SaltVersion("Holmium" , info=3057) + ERBIUM = SaltVersion("Erbium" , info=3058) + THULIUM = SaltVersion("Thulium" , info=3059) + YTTERBIUM = SaltVersion("Ytterbium" , info=3060) + LUTETIUM = SaltVersion("Lutetium" , info=3061) + HAFNIUM = SaltVersion("Hafnium" , info=3062) + TANTALUM = SaltVersion("Tantalum" , info=3063) + TUNGSTEN = SaltVersion("Tungsten" , info=3064) + RHENIUM = SaltVersion("Rhenium" , info=3065) + OSMIUM = SaltVersion("Osmium" , info=3066) + IRIDIUM = SaltVersion("Iridium" , info=3067) + PLATINUM = SaltVersion("Platinum" , info=3068) + GOLD = SaltVersion("Gold" , info=3069) + MERCURY = SaltVersion("Mercury" , info=3070) + THALLIUM = SaltVersion("Thallium" , info=3071) + LEAD = SaltVersion("Lead" , info=3072) + BISMUTH = SaltVersion("Bismuth" , info=3073) + POLONIUM = SaltVersion("Polonium" , info=3074) + ASTATINE = SaltVersion("Astatine" , info=3075) + RADON = SaltVersion("Radon" , info=3076) + FRANCIUM = SaltVersion("Francium" , info=3077) + RADIUM = SaltVersion("Radium" , info=3078) + ACTINIUM = SaltVersion("Actinium" , info=3079) + THORIUM = SaltVersion("Thorium" , info=3080) + PROTACTINIUM = SaltVersion("Protactinium" , info=3081) + URANIUM = SaltVersion("Uranium" , info=3082) + NEPTUNIUM = SaltVersion("Neptunium" , info=3083) + PLUTONIUM = SaltVersion("Plutonium" , info=3084) + AMERICIUM = SaltVersion("Americium" , info=3085) + CURIUM = SaltVersion("Curium" , info=3086) + BERKELIUM = SaltVersion("Berkelium" , info=3087) + CALIFORNIUM = SaltVersion("Californium" , info=3088) + EINSTEINIUM = SaltVersion("Einsteinium" , info=3089) + FERMIUM = SaltVersion("Fermium" , info=3090) + MENDELEVIUM = SaltVersion("Mendelevium" , info=3091) + NOBELIUM = SaltVersion("Nobelium" , info=3092) + LAWRENCIUM = SaltVersion("Lawrencium" , info=3093) + RUTHERFORDIUM = SaltVersion("Rutherfordium", info=3094) + DUBNIUM = SaltVersion("Dubnium" , info=3095) + SEABORGIUM = SaltVersion("Seaborgium" , info=3096) + BOHRIUM = SaltVersion("Bohrium" , info=3097) + HASSIUM = SaltVersion("Hassium" , info=3098) + MEITNERIUM = SaltVersion("Meitnerium" , info=3099) + DARMSTADTIUM = SaltVersion("Darmstadtium" , info=3100) + ROENTGENIUM = SaltVersion("Roentgenium" , info=3101) + COPERNICIUM = SaltVersion("Copernicium" , info=3102) + NIHONIUM = SaltVersion("Nihonium" , info=3103) + FLEROVIUM = SaltVersion("Flerovium" , info=3104) + MOSCOVIUM = SaltVersion("Moscovium" , info=3105) + LIVERMORIUM = SaltVersion("Livermorium" , info=3106) + TENNESSINE = SaltVersion("Tennessine" , info=3107) + OGANESSON = SaltVersion("Oganesson" , info=3108) # <---- Please refrain from fixing whitespace ----------------------------------- # The idea is to keep this readable. # ------------------------------------------------------------------------------- @@ -324,9 +324,7 @@ class SaltStackVersion: self.mbugfix = mbugfix self.pre_type = pre_type self.pre_num = pre_num - if self.can_have_dot_zero(major): - vnames_key = (major, 0) - elif self.new_version(major): + if self.new_version(major): vnames_key = (major,) else: vnames_key = (major, minor) From 8f57078f4cec23183f414256aebfb140e5d6fdfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Tue, 27 Jun 2023 11:59:41 +0100 Subject: [PATCH 16/46] Add changes suggested by pre-commit (cherry picked from commit 767303a3dc97b0590e2dcdb61eb5a975066f98d0) --- salt/version.py | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/salt/version.py b/salt/version.py index 22ba1905c4b..c99ef9414e7 100644 --- a/salt/version.py +++ b/salt/version.py @@ -355,15 +355,13 @@ class SaltStackVersion: ) match = cls.git_describe_regex.match(vstr) if not match: - raise ValueError( - "Unable to parse version string: '{}'".format(version_string) - ) + raise ValueError(f"Unable to parse version string: '{version_string}'") return cls(*match.groups()) @classmethod def from_name(cls, name): if name.lower() not in cls.LNAMES: - raise ValueError("Named version '{}' is not known".format(name)) + raise ValueError(f"Named version '{name}' is not known") return cls(*cls.LNAMES[name.lower()]) @classmethod @@ -446,22 +444,22 @@ class SaltStackVersion: @property def string(self): if self.new_version(self.major): - version_string = "{}".format(self.major) + version_string = f"{self.major}" if self.minor: - version_string = "{}.{}".format(self.major, self.minor) + version_string = f"{self.major}.{self.minor}" if not self.minor and self.can_have_dot_zero(self.major): - version_string = "{}.{}".format(self.major, self.minor) + version_string = f"{self.major}.{self.minor}" else: - version_string = "{}.{}.{}".format(self.major, self.minor, self.bugfix) + version_string = f"{self.major}.{self.minor}.{self.bugfix}" if self.mbugfix: - version_string += ".{}".format(self.mbugfix) + version_string += f".{self.mbugfix}" if self.pre_type: - version_string += "{}{}".format(self.pre_type, self.pre_num) + version_string += f"{self.pre_type}{self.pre_num}" if self.noc and self.sha: noc = self.noc if noc < 0: noc = "0na" - version_string += "+{}.{}".format(noc, self.sha) + version_string += f"+{noc}.{self.sha}" return version_string @property @@ -476,7 +474,7 @@ class SaltStackVersion: if self.sse: version_string += " Enterprise" if (self.major, self.minor) in self.RMATCH: - version_string += " ({})".format(self.RMATCH[(self.major, self.minor)]) + version_string += f" ({self.RMATCH[(self.major, self.minor)]})" return version_string @property @@ -500,7 +498,7 @@ class SaltStackVersion: other = SaltStackVersion(*other) else: raise ValueError( - "Cannot instantiate Version from type '{}'".format(type(other)) + f"Cannot instantiate Version from type '{type(other)}'" ) pre_type = self.pre_index other_pre_type = other.pre_index @@ -549,24 +547,24 @@ class SaltStackVersion: def __repr__(self): parts = [] if self.name: - parts.append("name='{}'".format(self.name)) - parts.extend(["major={}".format(self.major), "minor={}".format(self.minor)]) + parts.append(f"name='{self.name}'") + parts.extend([f"major={self.major}", f"minor={self.minor}"]) if self.new_version(self.major): if not self.can_have_dot_zero(self.major) and not self.minor: parts.remove("".join([x for x in parts if re.search("^minor*", x)])) else: - parts.extend(["bugfix={}".format(self.bugfix)]) + parts.extend([f"bugfix={self.bugfix}"]) if self.mbugfix: - parts.append("minor-bugfix={}".format(self.mbugfix)) + parts.append(f"minor-bugfix={self.mbugfix}") if self.pre_type: - parts.append("{}={}".format(self.pre_type, self.pre_num)) + parts.append(f"{self.pre_type}={self.pre_num}") noc = self.noc if noc == -1: noc = "0na" if noc and self.sha: - parts.extend(["noc={}".format(noc), "sha={}".format(self.sha)]) + parts.extend([f"noc={noc}", f"sha={self.sha}"]) return "<{} {}>".format(self.__class__.__name__, " ".join(parts)) @@ -613,7 +611,7 @@ def __discover_version(saltstack_version): "v[0-9]*", "--always", ], - **kwargs + **kwargs, ) out, err = process.communicate() @@ -808,7 +806,7 @@ def system_information(): # ie: R2 if re.match(r"^R\d+$", item): release = item - release = "{}Server{}".format(version, release) + release = f"{version}Server{release}" else: for item in product_name.split(" "): # If it's a number, decimal number, Thin or Vista, then it's the @@ -908,7 +906,7 @@ def versions_report(include_salt_cloud=False, include_extensions=True): if ver_type == "Salt Extensions" and ver_type not in ver_info: # No salt Extensions to report continue - info.append("{}:".format(ver_type)) + info.append(f"{ver_type}:") # List dependencies in alphabetical, case insensitive order for name in sorted(ver_info[ver_type], key=lambda x: x.lower()): ver = fmt.format( From c6f5d7e7391436fd162083e23f874ed7e82b334d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Tue, 27 Jun 2023 12:20:50 +0100 Subject: [PATCH 17/46] Add some new and fix unit tests (cherry picked from commit 69696e6fd74bf470524fcc7d67e8c5e1dad890c3) --- .../pytests/unit/modules/test_salt_version.py | 43 ++++++++++++++++++- tests/pytests/unit/test_version.py | 10 +++-- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/tests/pytests/unit/modules/test_salt_version.py b/tests/pytests/unit/modules/test_salt_version.py index 6d734f6a764..f6c25630e03 100644 --- a/tests/pytests/unit/modules/test_salt_version.py +++ b/tests/pytests/unit/modules/test_salt_version.py @@ -21,7 +21,7 @@ def test_mocked_objects(): for k, v in salt.version.SaltStackVersion.LNAMES.items(): assert k == k.lower() assert isinstance(v, tuple) - if sv.new_version(major=v[0]) and not sv.can_have_dot_zero(major=v[0]): + if sv.new_version(major=v[0]): assert len(v) == 1 else: assert len(v) == 2 @@ -64,6 +64,13 @@ def test_get_release_number_success_new_version(): assert salt_version.get_release_number("Neon") == "3000" +def test_get_release_number_success_new_version_with_dot(): + """ + Test that a version is returned for new versioning (3006) + """ + assert salt_version.get_release_number("Sulfur") == "3006" + + def test_equal_success(): """ Test that the current version is equal to the codename @@ -83,6 +90,16 @@ def test_equal_success_new_version(): assert salt_version.equal("foo") is True +def test_equal_success_new_version_with_dot(): + """ + Test that the current version is equal to the codename + while using the new versioning + """ + with patch("salt.version.SaltStackVersion", MagicMock(return_value="3006.1")): + with patch("salt.version.SaltStackVersion.LNAMES", {"foo": (3006,)}): + assert salt_version.equal("foo") is True + + def test_equal_older_codename(): """ Test that when an older codename is passed in, the function returns False. @@ -142,6 +159,17 @@ def test_greater_than_success_new_version(): assert salt_version.greater_than("Nitrogen") is True +def test_greater_than_success_new_version_with_dot(): + """ + Test that the current version is newer than the codename + """ + with patch( + "salt.modules.salt_version.get_release_number", MagicMock(return_value="3000") + ): + with patch("salt.version.SaltStackVersion", MagicMock(return_value="3006.0")): + assert salt_version.greater_than("Neon") is True + + def test_greater_than_with_equal_codename(): """ Test that when an equal codename is passed in, the function returns False. @@ -200,6 +228,19 @@ def test_less_than_success_new_version(): assert salt_version.less_than("Fluorine") is True +def test_less_than_success_new_version_with_dot(): + """ + Test that when a newer codename is passed in, the function returns True + using new version + """ + with patch("salt.version.SaltStackVersion", MagicMock(return_value="2018.3.2")): + with patch( + "salt.modules.salt_version.get_release_number", + MagicMock(return_value="3006"), + ): + assert salt_version.less_than("Fluorine") is True + + def test_less_than_with_equal_codename(): """ Test that when an equal codename is passed in, the function returns False. diff --git a/tests/pytests/unit/test_version.py b/tests/pytests/unit/test_version.py index 73befea4cf4..1cb94c619ca 100644 --- a/tests/pytests/unit/test_version.py +++ b/tests/pytests/unit/test_version.py @@ -187,7 +187,7 @@ def test_string_new_version_minor(): ver = SaltStackVersion(major=maj_ver, minor=min_ver) assert ver.minor == min_ver assert not ver.bugfix - assert ver.string == "{}.{}".format(maj_ver, min_ver) + assert ver.string == f"{maj_ver}.{min_ver}" def test_string_new_version_minor_as_string(): @@ -201,13 +201,13 @@ def test_string_new_version_minor_as_string(): ver = SaltStackVersion(major=maj_ver, minor=min_ver) assert ver.minor == int(min_ver) assert not ver.bugfix - assert ver.string == "{}.{}".format(maj_ver, min_ver) + assert ver.string == f"{maj_ver}.{min_ver}" # This only seems to happen on a cloned repo without its tags maj_ver = "3000" min_ver = "" ver = SaltStackVersion(major=maj_ver, minor=min_ver) - assert ver.minor is None, "{!r} is not {!r}".format(ver.minor, min_ver) + assert ver.minor is None, f"{ver.minor!r} is not {min_ver!r}" assert not ver.bugfix assert ver.string == maj_ver @@ -222,7 +222,7 @@ def test_string_old_version(): min_ver = "2" ver = SaltStackVersion(major=maj_ver, minor=min_ver) assert ver.bugfix == 0 - assert ver.string == "{}.{}.0".format(maj_ver, min_ver) + assert ver.string == f"{maj_ver}.{min_ver}.0" @pytest.mark.parametrize( @@ -537,6 +537,8 @@ def test_versions_report_no_extensions_available(): ("3000.1", "3000.1", "Neon"), ("3005", "3005", "Phosphorus"), ("3006", "3006.0", "Sulfur"), + ("3006.0", "3006.0", "Sulfur"), + ("3006.1", "3006.1", "Sulfur"), ("3015.1", "3015.1", "Manganese"), ("3109.3", "3109.3", None), ], From 7f6d61b95455e58eef2630971ca32e956927f89d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Tue, 27 Jun 2023 13:10:05 +0100 Subject: [PATCH 18/46] Add changelog file (cherry picked from commit 4cd8fe14d422be14d22c0f9a41d08b3b45648191) --- changelog/64554.fixed.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/64554.fixed.md diff --git a/changelog/64554.fixed.md b/changelog/64554.fixed.md new file mode 100644 index 00000000000..56d03053a2c --- /dev/null +++ b/changelog/64554.fixed.md @@ -0,0 +1 @@ +Fix detection of Salt codename by "salt_version" execution module From 6bce148a78ae873d54869b4fcd9f2e83886297c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Wed, 28 Jun 2023 12:38:51 +0100 Subject: [PATCH 19/46] Fix SaltStackVersion string for new versions format (cherry picked from commit a2abb1a4506fd8fab29570592e1b97d5874752c2) --- salt/version.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/salt/version.py b/salt/version.py index c99ef9414e7..e174d8bfb1f 100644 --- a/salt/version.py +++ b/salt/version.py @@ -473,8 +473,12 @@ class SaltStackVersion: version_string = self.string if self.sse: version_string += " Enterprise" - if (self.major, self.minor) in self.RMATCH: - version_string += f" ({self.RMATCH[(self.major, self.minor)]})" + if self.new_version(self.major): + rmatch_key = (self.major,) + else: + rmatch_key = (self.major, self.minor) + if rmatch_key in self.RMATCH: + version_string += f" ({self.RMATCH[rmatch_key]})" return version_string @property From f29674140004aa74cbc9531d703b479f16a7c6b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Wed, 28 Jun 2023 13:24:20 +0100 Subject: [PATCH 20/46] Rename changelog file according to bug report (cherry picked from commit 8540a3fdd43d43d672e8c8a89188ba19c5f7eea6) --- changelog/{64554.fixed.md => 64306.fixed.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog/{64554.fixed.md => 64306.fixed.md} (100%) diff --git a/changelog/64554.fixed.md b/changelog/64306.fixed.md similarity index 100% rename from changelog/64554.fixed.md rename to changelog/64306.fixed.md From 0179b39e47a53edaab02d38c6ecdfa55f53ac4c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Wed, 28 Jun 2023 14:11:46 +0100 Subject: [PATCH 21/46] Do not crash when passing numbers to 'salt_version.get_release_number' (cherry picked from commit 3693a0db427a72019076e728fc55e24320356502) --- salt/modules/salt_version.py | 4 ++++ tests/pytests/unit/modules/test_salt_version.py | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/salt/modules/salt_version.py b/salt/modules/salt_version.py index 1b5421fee4a..3c6b475c840 100644 --- a/salt/modules/salt_version.py +++ b/salt/modules/salt_version.py @@ -35,6 +35,7 @@ import logging import salt.utils.versions import salt.version +from salt.exceptions import CommandExecutionError log = logging.getLogger(__name__) @@ -66,6 +67,9 @@ def get_release_number(name): salt '*' salt_version.get_release_number 'Oxygen' """ + if not isinstance(name, str): + raise CommandExecutionError("'name' argument must be a string") + name = name.lower() version_map = salt.version.SaltStackVersion.LNAMES version = version_map.get(name) diff --git a/tests/pytests/unit/modules/test_salt_version.py b/tests/pytests/unit/modules/test_salt_version.py index f6c25630e03..4b7a7cd0731 100644 --- a/tests/pytests/unit/modules/test_salt_version.py +++ b/tests/pytests/unit/modules/test_salt_version.py @@ -2,8 +2,11 @@ Unit tests for salt/modules/salt_version.py """ +import pytest + import salt.modules.salt_version as salt_version import salt.version +from salt.exceptions import CommandExecutionError from tests.support.mock import MagicMock, patch @@ -241,6 +244,15 @@ def test_less_than_success_new_version_with_dot(): assert salt_version.less_than("Fluorine") is True +def test_less_than_do_not_crash_when_input_is_a_number(): + """ + Test that less_than do not crash when unexpected inputs + """ + with patch("salt.version.SaltStackVersion", MagicMock(return_value="2018.3.2")): + with pytest.raises(CommandExecutionError): + salt_version.less_than(1234) + + def test_less_than_with_equal_codename(): """ Test that when an equal codename is passed in, the function returns False. From ccd07f9d24b751c9db2c377c047fa6112e40763c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Thu, 29 Jun 2023 09:51:07 +0100 Subject: [PATCH 22/46] Fix salt_version execution module documentation (cherry picked from commit a92ddf5a415d0856dd92be28cbb320e508deef89) --- salt/modules/salt_version.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/salt/modules/salt_version.py b/salt/modules/salt_version.py index 3c6b475c840..99dae5f61a5 100644 --- a/salt/modules/salt_version.py +++ b/salt/modules/salt_version.py @@ -20,7 +20,7 @@ A simple example might be something like the following: .. code-block:: jinja {# a boolean check #} - {% set option_deprecated = salt['salt_version.less_than']("3001") %} + {% set option_deprecated = salt['salt_version.less_than']("Sodium") %} {% if option_deprecated %} @@ -52,7 +52,7 @@ def __virtual__(): def get_release_number(name): """ Returns the release number of a given release code name in a - ``MAJOR.PATCH`` format. + ``MAJOR.PATCH`` format (for Salt versions < 3000) or ``MAJOR`` for newer Salt versions. If the release name has not been given an assigned release number, the function returns a string. If the release cannot be found, it returns From 0083c037725daccec0b161aa2c12063bfd7d3fdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Fri, 30 Jun 2023 12:47:05 +0100 Subject: [PATCH 23/46] Fix test to get proper formatted version (cherry picked from commit db5a9a1b4aac2e0d0841ff3cffac0af3e9564556) --- tests/pytests/functional/cli/test_salt_run_.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pytests/functional/cli/test_salt_run_.py b/tests/pytests/functional/cli/test_salt_run_.py index 66c28fc3aae..63841f9fb8c 100644 --- a/tests/pytests/functional/cli/test_salt_run_.py +++ b/tests/pytests/functional/cli/test_salt_run_.py @@ -80,6 +80,6 @@ def test_versions_report(salt_run_cli): def test_salt_run_version(salt_run_cli): - expected = salt.version.__version__ + expected = salt.version.__saltstack_version__.formatted_version ret = salt_run_cli.run("--version") assert f"cli_salt_run.py {expected}\n" == ret.stdout From 873e96db5cc40ea385aa5a5dfb587eedd066d418 Mon Sep 17 00:00:00 2001 From: Tim Hildebrandt <118898773+TimHiCe@users.noreply.github.com> Date: Tue, 6 Jun 2023 18:18:54 +0200 Subject: [PATCH 24/46] Update chocolatey.py / Search for choco.exe chocolatey.exe was renamed to choco.exe by Chocolatey in Version 2.0.0 (cherry picked from commit fd09ab7efb29d83223002dfa3526db36c5b23574) --- salt/modules/chocolatey.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/salt/modules/chocolatey.py b/salt/modules/chocolatey.py index caa7b0bae8f..dc3dd62f651 100644 --- a/salt/modules/chocolatey.py +++ b/salt/modules/chocolatey.py @@ -111,6 +111,9 @@ def _find_chocolatey(): os.path.join( os.environ.get("ProgramData"), "Chocolatey", "bin", "chocolatey.exe" ), + os.path.join( + os.environ.get("ProgramData"), "Chocolatey", "bin", "choco.exe" + ), os.path.join( os.environ.get("SystemDrive"), "Chocolatey", "bin", "chocolatey.bat" ), From fc99dfbb790d629075735768a380643c156eaaea Mon Sep 17 00:00:00 2001 From: Tim Hildebrandt <118898773+TimHiCe@users.noreply.github.com> Date: Thu, 8 Jun 2023 18:34:23 +0200 Subject: [PATCH 25/46] Update chocolatey.py Change environ key of new lication to "ProgramDataChoco" to not overwrite the environ of the chocolatey.exe path. (cherry picked from commit 52da6c2b589ede50b659031213e8675782ec0e84) --- salt/modules/chocolatey.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/modules/chocolatey.py b/salt/modules/chocolatey.py index dc3dd62f651..ff903632518 100644 --- a/salt/modules/chocolatey.py +++ b/salt/modules/chocolatey.py @@ -112,7 +112,7 @@ def _find_chocolatey(): os.environ.get("ProgramData"), "Chocolatey", "bin", "chocolatey.exe" ), os.path.join( - os.environ.get("ProgramData"), "Chocolatey", "bin", "choco.exe" + os.environ.get("ProgramDataChoco"), "Chocolatey", "bin", "choco.exe" ), os.path.join( os.environ.get("SystemDrive"), "Chocolatey", "bin", "chocolatey.bat" From f7be8159ff60b4c66b391ec04121727f306d408b Mon Sep 17 00:00:00 2001 From: Tim Hildebrandt <118898773+TimHiCe@users.noreply.github.com> Date: Thu, 8 Jun 2023 18:58:24 +0200 Subject: [PATCH 26/46] Update test_chocolatey.py Add test for choco.exe in ProgramData (cherry picked from commit 45e1ee93688bef5e0eff8c62893a2c7949fe4ef0) --- tests/pytests/unit/modules/test_chocolatey.py | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/tests/pytests/unit/modules/test_chocolatey.py b/tests/pytests/unit/modules/test_chocolatey.py index e9adc167b70..2d09185b23f 100644 --- a/tests/pytests/unit/modules/test_chocolatey.py +++ b/tests/pytests/unit/modules/test_chocolatey.py @@ -25,12 +25,19 @@ def choco_path(): @pytest.fixture(scope="module") -def choco_path_pd(): +def chocolatey_path_pd(): return os.path.join( os.environ.get("ProgramData"), "Chocolatey", "bin", "chocolatey.exe" ) +@pytest.fixture(scope="module") +def choco_path_pd(): + return os.path.join( + os.environ.get("ProgramData"), "Chocolatey", "bin", "choco.exe" + ) + + @pytest.fixture(scope="module") def choco_path_sd(): return os.path.join( @@ -133,9 +140,24 @@ def test__find_chocolatey_which(choco_path): assert chocolatey.__context__["chocolatey._path"] == expected -def test__find_chocolatey_programdata(mock_false, mock_true, choco_path_pd): +def test__find_chocolatey_programdata(mock_false, mock_true, chocolatey_path_pd): """ - Test _find_chocolatey when found in ProgramData + Test _find_chocolatey when found in ProgramData and named chocolatey.exe + """ + with patch.dict(chocolatey.__salt__, {"cmd.which": mock_false}), patch( + "os.path.isfile", mock_true + ): + result = chocolatey._find_chocolatey() + expected = choco_path_pd + # Does it return the correct path + assert result == expected + # Does it populate __context__ + assert chocolatey.__context__["chocolatey._path"] == expected + + +def test__find_choco_programdata(mock_false, mock_true, choco_path_pd): + """ + Test _find_chocolatey when found in ProgramData and named choco.exe """ with patch.dict(chocolatey.__salt__, {"cmd.which": mock_false}), patch( "os.path.isfile", mock_true From a2262299db3c5e7ab25022603b5a87ab391452b0 Mon Sep 17 00:00:00 2001 From: Tim Hildebrandt <118898773+TimHiCe@users.noreply.github.com> Date: Thu, 8 Jun 2023 20:32:35 +0200 Subject: [PATCH 27/46] Update chocolatey.py Bug Fix the last commit (cherry picked from commit 11b3b913e893cf5b014e718d52c8b2e8f08009c1) --- salt/modules/chocolatey.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/modules/chocolatey.py b/salt/modules/chocolatey.py index ff903632518..dc3dd62f651 100644 --- a/salt/modules/chocolatey.py +++ b/salt/modules/chocolatey.py @@ -112,7 +112,7 @@ def _find_chocolatey(): os.environ.get("ProgramData"), "Chocolatey", "bin", "chocolatey.exe" ), os.path.join( - os.environ.get("ProgramDataChoco"), "Chocolatey", "bin", "choco.exe" + os.environ.get("ProgramData"), "Chocolatey", "bin", "choco.exe" ), os.path.join( os.environ.get("SystemDrive"), "Chocolatey", "bin", "chocolatey.bat" From 9f0d496e8c1ca0ca47fa42911199213654652057 Mon Sep 17 00:00:00 2001 From: Tim Hildebrandt <118898773+TimHiCe@users.noreply.github.com> Date: Thu, 8 Jun 2023 20:40:55 +0200 Subject: [PATCH 28/46] Add changelog (cherry picked from commit 7b07640b32581836cc27cfd618c83cac4f56b7d1) --- changelog/64427.fixed.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/64427.fixed.md diff --git a/changelog/64427.fixed.md b/changelog/64427.fixed.md new file mode 100644 index 00000000000..74f5b125579 --- /dev/null +++ b/changelog/64427.fixed.md @@ -0,0 +1 @@ +Add search for %ProgramData%\Chocolatey\choco.exe to determine if Chocolatey is installed or not From 0099f568a124817235996228f7caf2c523be4adf Mon Sep 17 00:00:00 2001 From: twangboy Date: Thu, 29 Jun 2023 16:13:14 -0600 Subject: [PATCH 29/46] Fix pre-commit (cherry picked from commit e8ccb262a612b645fb965bc3217b102ad404f467) --- salt/modules/chocolatey.py | 16 +++++++--------- tests/pytests/unit/modules/test_chocolatey.py | 4 +--- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/salt/modules/chocolatey.py b/salt/modules/chocolatey.py index dc3dd62f651..06794946d55 100644 --- a/salt/modules/chocolatey.py +++ b/salt/modules/chocolatey.py @@ -111,9 +111,7 @@ def _find_chocolatey(): os.path.join( os.environ.get("ProgramData"), "Chocolatey", "bin", "chocolatey.exe" ), - os.path.join( - os.environ.get("ProgramData"), "Chocolatey", "bin", "choco.exe" - ), + os.path.join(os.environ.get("ProgramData"), "Chocolatey", "bin", "choco.exe"), os.path.join( os.environ.get("SystemDrive"), "Chocolatey", "bin", "chocolatey.bat" ), @@ -210,7 +208,7 @@ def bootstrap(force=False, source=None): except CommandExecutionError: choc_path = None if choc_path and not force: - return "Chocolatey found at {}".format(choc_path) + return f"Chocolatey found at {choc_path}" temp_dir = tempfile.gettempdir() @@ -338,7 +336,7 @@ def bootstrap(force=False, source=None): if not os.path.exists(script): raise CommandExecutionError( - "Failed to find Chocolatey installation script: {}".format(script) + f"Failed to find Chocolatey installation script: {script}" ) # Run the Chocolatey bootstrap @@ -380,7 +378,7 @@ def unbootstrap(): if os.path.exists(choco_dir): log.debug("Removing Chocolatey directory: %s", choco_dir) __salt__["file.remove"](path=choco_dir, force=True) - removed.append("Removed Directory: {}".format(choco_dir)) + removed.append(f"Removed Directory: {choco_dir}") else: known_paths = [ os.path.join(os.environ.get("ProgramData"), "Chocolatey"), @@ -390,7 +388,7 @@ def unbootstrap(): if os.path.exists(path): log.debug("Removing Chocolatey directory: %s", path) __salt__["file.remove"](path=path, force=True) - removed.append("Removed Directory: {}".format(path)) + removed.append(f"Removed Directory: {path}") # Delete all Chocolatey environment variables for env_var in __salt__["environ.items"](): @@ -402,14 +400,14 @@ def unbootstrap(): __salt__["environ.setval"]( key=env_var, val=False, false_unsets=True, permanent="HKCU" ) - removed.append("Removed Environment Var: {}".format(env_var)) + removed.append(f"Removed Environment Var: {env_var}") # Remove Chocolatey from the path: for path in __salt__["win_path.get_path"](): if "chocolatey" in path.lower(): log.debug("Removing Chocolatey path item: %s", path) __salt__["win_path.remove"](path=path, rehash=True) - removed.append("Removed Path Item: {}".format(path)) + removed.append(f"Removed Path Item: {path}") return removed diff --git a/tests/pytests/unit/modules/test_chocolatey.py b/tests/pytests/unit/modules/test_chocolatey.py index 2d09185b23f..74c29d36fe8 100644 --- a/tests/pytests/unit/modules/test_chocolatey.py +++ b/tests/pytests/unit/modules/test_chocolatey.py @@ -33,9 +33,7 @@ def chocolatey_path_pd(): @pytest.fixture(scope="module") def choco_path_pd(): - return os.path.join( - os.environ.get("ProgramData"), "Chocolatey", "bin", "choco.exe" - ) + return os.path.join(os.environ.get("ProgramData"), "Chocolatey", "bin", "choco.exe") @pytest.fixture(scope="module") From 84df80accb45e8ee868a932ed44fcd2a137fcfd5 Mon Sep 17 00:00:00 2001 From: twangboy Date: Thu, 29 Jun 2023 17:12:28 -0600 Subject: [PATCH 30/46] Fix failing tests (cherry picked from commit 1ef90cbdc7203f97775edb7666db86a41eb9fc15) --- tests/pytests/unit/modules/test_chocolatey.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/pytests/unit/modules/test_chocolatey.py b/tests/pytests/unit/modules/test_chocolatey.py index 74c29d36fe8..c4b955321d1 100644 --- a/tests/pytests/unit/modules/test_chocolatey.py +++ b/tests/pytests/unit/modules/test_chocolatey.py @@ -146,19 +146,20 @@ def test__find_chocolatey_programdata(mock_false, mock_true, chocolatey_path_pd) "os.path.isfile", mock_true ): result = chocolatey._find_chocolatey() - expected = choco_path_pd + expected = chocolatey_path_pd # Does it return the correct path assert result == expected # Does it populate __context__ assert chocolatey.__context__["chocolatey._path"] == expected -def test__find_choco_programdata(mock_false, mock_true, choco_path_pd): +def test__find_choco_programdata(mock_false, choco_path_pd): """ Test _find_chocolatey when found in ProgramData and named choco.exe """ + mock_is_file = MagicMock(side_effect=[False, True]) with patch.dict(chocolatey.__salt__, {"cmd.which": mock_false}), patch( - "os.path.isfile", mock_true + "os.path.isfile", mock_is_file ): result = chocolatey._find_chocolatey() expected = choco_path_pd @@ -173,7 +174,7 @@ def test__find_chocolatey_systemdrive(mock_false, choco_path_sd): Test _find_chocolatey when found on SystemDrive (older versions) """ with patch.dict(chocolatey.__salt__, {"cmd.which": mock_false}), patch( - "os.path.isfile", MagicMock(side_effect=[False, True]) + "os.path.isfile", MagicMock(side_effect=[False, False, True]) ): result = chocolatey._find_chocolatey() expected = choco_path_sd From bba34f19630b5f13db7835b54de1233e4d5c130c Mon Sep 17 00:00:00 2001 From: MKLeb Date: Thu, 29 Jun 2023 16:49:04 -0400 Subject: [PATCH 31/46] Migrate the old service state tests to pytest --- tests/filename_map.yml | 2 +- tests/integration/states/test_service.py | 119 ----------- .../integration/states/test_service.py | 184 ++++++++++++++++++ 3 files changed, 185 insertions(+), 120 deletions(-) delete mode 100644 tests/integration/states/test_service.py create mode 100644 tests/pytests/integration/states/test_service.py diff --git a/tests/filename_map.yml b/tests/filename_map.yml index 968e1f32195..50411596395 100644 --- a/tests/filename_map.yml +++ b/tests/filename_map.yml @@ -31,7 +31,7 @@ salt/modules/(aix_group|groupadd|mac_group|pw_group|solaris_group|win_groupadd)\ salt/modules/(debian_service|freebsdservice|gentoo_service|launchctl_service|mac_service|netbsdservice|openbsdrcctl_service|openbsdservice|rh_service|runit|linux_service|smf_service|systemd_service|upstart_service|win_service)\.py: - pytests.unit.states.test_service - integration.modules.test_service - - integration.states.test_service + - pytests.integration.states.test_service salt/modules/ansiblegate.py: diff --git a/tests/integration/states/test_service.py b/tests/integration/states/test_service.py deleted file mode 100644 index 8607c92b278..00000000000 --- a/tests/integration/states/test_service.py +++ /dev/null @@ -1,119 +0,0 @@ -""" -Tests for the service state -""" - -import re - -import pytest - -import salt.utils.path -import salt.utils.platform -from tests.support.case import ModuleCase -from tests.support.mixins import SaltReturnAssertsMixin - -INIT_DELAY = 5 - - -@pytest.mark.windows_whitelisted -@pytest.mark.destructive_test -class ServiceTest(ModuleCase, SaltReturnAssertsMixin): - """ - Validate the service state - """ - - def setUp(self): - self.service_name = "cron" - cmd_name = "crontab" - os_family = self.run_function("grains.get", ["os_family"]) - os_release = self.run_function("grains.get", ["osrelease"]) - is_systemd = self.run_function("grains.get", ["systemd"]) - self.stopped = False - self.running = True - if os_family == "RedHat": - self.service_name = "crond" - elif os_family == "Arch": - self.service_name = "sshd" - cmd_name = "systemctl" - elif os_family == "MacOS": - self.service_name = "com.apple.AirPlayXPCHelper" - elif os_family == "Windows": - self.service_name = "Spooler" - - self.pre_srv_enabled = ( - True - if self.service_name in self.run_function("service.get_enabled") - else False - ) - self.post_srv_disable = False - if not self.pre_srv_enabled: - self.run_function("service.enable", name=self.service_name) - self.post_srv_disable = True - - if os_family != "Windows" and salt.utils.path.which(cmd_name) is None: - self.skipTest("{} is not installed".format(cmd_name)) - - if is_systemd and self.run_function("service.offline"): - self.skipTest("systemd is OFFLINE") - - def tearDown(self): - if self.post_srv_disable: - self.run_function("service.disable", name=self.service_name) - - def check_service_status(self, exp_return): - """ - helper method to check status of service - """ - check_status = self.run_function("service.status", name=self.service_name) - - try: - if not re.match(exp_return, check_status): - self.fail("status of service is not returning correctly") - except TypeError: - if check_status is not exp_return: - self.fail("status of service is not returning correctly") - - @pytest.mark.slow_test - def test_service_running(self): - """ - test service.running state module - """ - if self.run_function("service.status", name=self.service_name): - stop_service = self.run_function("service.stop", name=self.service_name) - self.assertTrue(stop_service) - self.check_service_status(self.stopped) - - if salt.utils.platform.is_darwin(): - # make sure the service is enabled on macosx - enable = self.run_function("service.enable", name=self.service_name) - - start_service = self.run_state("service.running", name=self.service_name) - self.assertTrue(start_service) - self.check_service_status(self.running) - - @pytest.mark.slow_test - def test_service_dead(self): - """ - test service.dead state module - """ - start_service = self.run_state("service.running", name=self.service_name) - self.assertSaltTrueReturn(start_service) - self.check_service_status(self.running) - - ret = self.run_state("service.dead", name=self.service_name) - self.assertSaltTrueReturn(ret) - self.check_service_status(self.stopped) - - @pytest.mark.slow_test - def test_service_dead_init_delay(self): - """ - test service.dead state module with init_delay arg - """ - start_service = self.run_state("service.running", name=self.service_name) - self.assertSaltTrueReturn(start_service) - self.check_service_status(self.running) - - ret = self.run_state( - "service.dead", name=self.service_name, init_delay=INIT_DELAY - ) - self.assertSaltTrueReturn(ret) - self.check_service_status(self.stopped) diff --git a/tests/pytests/integration/states/test_service.py b/tests/pytests/integration/states/test_service.py new file mode 100644 index 00000000000..2718be3cc45 --- /dev/null +++ b/tests/pytests/integration/states/test_service.py @@ -0,0 +1,184 @@ +""" +Tests for the service state +""" + +import os + +import pytest + +import salt.utils.path +import salt.utils.platform + +INIT_DELAY = 5 + + +pytestmark = [ + pytest.mark.windows_whitelisted, + pytest.mark.destructive_test, + pytest.mark.slow_test, +] + + +STOPPED = False +RUNNING = True + + +@pytest.fixture +def service_name(grains, salt_cli, salt_minion): + # For local testing purposes + env_name = os.environ.get("SALT_SERVICE_STATE_TEST_SERVICE") + if env_name is not None: + return env_name + + service_name = "cron" + cmd_name = "crontab" + os_family = grains["os_family"] + is_systemd = grains["systemd"] + if os_family == "RedHat": + service_name = "crond" + elif os_family == "Arch": + service_name = "sshd" + cmd_name = "systemctl" + elif os_family == "MacOS": + service_name = "com.apple.AirPlayXPCHelper" + elif os_family == "Windows": + service_name = "Spooler" + + if os_family != "Windows" and salt.utils.path.which(cmd_name) is None: + pytest.skip("{} is not installed".format(cmd_name)) + + if is_systemd and salt_cli.run("service.offline", minion_tgt=salt_minion.id): + pytest.skip("systemd is OFFLINE") + + return service_name + + +@pytest.fixture(autouse=True) +def setup_service(service_name, salt_cli, salt_minion): + pre_srv_enabled = ( + True + if service_name + in salt_cli.run("service.get_enabled", minion_tgt=salt_minion.id).stdout + else False + ) + post_srv_disable = False + if not pre_srv_enabled: + salt_cli.run("service.enable", service_name, minion_tgt=salt_minion.id) + post_srv_disable = True + yield post_srv_disable + if post_srv_disable: + salt_cli.run("service.disable", service_name, minion_tgt=salt_minion.id) + + +# def setUp(self): +# self.service_name = "cron" +# cmd_name = "crontab" +# os_family = self.run_function("grains.get", ["os_family"]) +# os_release = self.run_function("grains.get", ["osrelease"]) +# is_systemd = self.run_function("grains.get", ["systemd"]) +# self.stopped = False +# self.running = True +# if os_family == "RedHat": +# self.service_name = "crond" +# elif os_family == "Arch": +# self.service_name = "sshd" +# cmd_name = "systemctl" +# elif os_family == "MacOS": +# self.service_name = "com.apple.AirPlayXPCHelper" +# elif os_family == "Windows": +# self.service_name = "Spooler" + +# self.pre_srv_enabled = ( +# True +# if self.service_name in self.run_function("service.get_enabled") +# else False +# ) +# self.post_srv_disable = False +# if not self.pre_srv_enabled: +# self.run_function("service.enable", name=self.service_name) +# self.post_srv_disable = True + +# if os_family != "Windows" and salt.utils.path.which(cmd_name) is None: +# self.skipTest("{} is not installed".format(cmd_name)) + +# if is_systemd and self.run_function("service.offline"): +# self.skipTest("systemd is OFFLINE") + +# def tearDown(self): +# if self.post_srv_disable: +# self.run_function("service.disable", name=self.service_name) + + +def check_service_status(exp_return, salt_cli, salt_minion, service_name): + """ + helper method to check status of service + """ + check_status = salt_cli.run( + "service.status", service_name, minion_tgt=salt_minion.id + ) + + if check_status.data is not exp_return: + pytest.fail("status of service is not returning correctly") + + +@pytest.mark.slow_test +def test_service_running(service_name, salt_minion, salt_cli): + """ + test service.running state module + """ + if salt_cli.run("service.status", service_name, minion_tgt=salt_minion.id): + stop_service = salt_cli.run( + "service.stop", service_name, minion_tgt=salt_minion.id + ) + assert stop_service.data is True + check_service_status(STOPPED, salt_cli, salt_minion, service_name) + + if salt.utils.platform.is_darwin(): + # make sure the service is enabled on macosx + enable = salt_cli.run("service.enable", service_name, minion_tgt=salt_minion.id) + + start_service = salt_cli.run( + "state.single", "service.running", service_name, minion_tgt=salt_minion.id + ) + assert next(iter(start_service.data.values()))["result"] is True + check_service_status(RUNNING, salt_cli, salt_minion, service_name) + + +@pytest.mark.slow_test +def test_service_dead(service_name, salt_cli, salt_minion): + """ + test service.dead state module + """ + start_service = salt_cli.run( + "state.single", "service.running", service_name, minion_tgt=salt_minion.id + ) + assert next(iter(start_service.data.values()))["result"] is True + check_service_status(RUNNING, salt_cli, salt_minion, service_name) + + ret = salt_cli.run( + "state.single", "service.dead", service_name, minion_tgt=salt_minion.id + ) + assert next(iter(ret.data.values()))["result"] is True + check_service_status(STOPPED, salt_cli, salt_minion, service_name) + + +@pytest.mark.slow_test +def test_service_dead_init_delay(service_name, salt_cli, salt_minion): + """ + test service.dead state module with init_delay arg + """ + start_service = salt_cli.run( + "state.single", "service.running", service_name, minion_tgt=salt_minion.id + ) + assert next(iter(start_service.data.values()))["result"] is True + check_service_status(RUNNING, salt_cli, salt_minion, service_name) + + ret = salt_cli.run( + "state.single", + "service.dead", + service_name, + init_delay=INIT_DELAY, + minion_tgt=salt_minion.id, + ) + assert next(iter(ret.data.values()))["result"] is True + check_service_status(STOPPED, salt_cli, salt_minion, service_name) From cb4f1be42e894a0d556aaf0d56738f25a613c560 Mon Sep 17 00:00:00 2001 From: MKLeb Date: Fri, 30 Jun 2023 16:29:36 -0400 Subject: [PATCH 32/46] Migrate the service module integration tests to pytest --- tests/filename_map.yml | 2 +- tests/integration/modules/test_service.py | 183 ----------------- .../integration/modules/test_service.py | 185 ++++++++++++++++++ .../integration/states/test_service.py | 45 +---- 4 files changed, 188 insertions(+), 227 deletions(-) delete mode 100644 tests/integration/modules/test_service.py create mode 100644 tests/pytests/integration/modules/test_service.py diff --git a/tests/filename_map.yml b/tests/filename_map.yml index 50411596395..caa5e472144 100644 --- a/tests/filename_map.yml +++ b/tests/filename_map.yml @@ -30,7 +30,7 @@ salt/modules/(aix_group|groupadd|mac_group|pw_group|solaris_group|win_groupadd)\ salt/modules/(debian_service|freebsdservice|gentoo_service|launchctl_service|mac_service|netbsdservice|openbsdrcctl_service|openbsdservice|rh_service|runit|linux_service|smf_service|systemd_service|upstart_service|win_service)\.py: - pytests.unit.states.test_service - - integration.modules.test_service + - pytests.integration.modules.test_service - pytests.integration.states.test_service diff --git a/tests/integration/modules/test_service.py b/tests/integration/modules/test_service.py deleted file mode 100644 index 7c070c6e2af..00000000000 --- a/tests/integration/modules/test_service.py +++ /dev/null @@ -1,183 +0,0 @@ -import pytest - -import salt.utils.path -import salt.utils.platform -import salt.utils.systemd -from tests.support.case import ModuleCase - - -@pytest.mark.destructive_test -@pytest.mark.windows_whitelisted -class ServiceModuleTest(ModuleCase): - """ - Module testing the service module - """ - - def setUp(self): - self.service_name = "cron" - cmd_name = "crontab" - os_family = self.run_function("grains.get", ["os_family"]) - os_release = self.run_function("grains.get", ["osrelease"]) - if os_family == "RedHat": - if os_release[0] == "7": - self.skipTest( - "Disabled on CentOS 7 until we can fix SSH connection issues." - ) - self.service_name = "crond" - elif os_family == "Arch": - self.service_name = "sshd" - cmd_name = "systemctl" - elif os_family == "NILinuxRT": - self.service_name = "syslog" - cmd_name = "syslog-ng" - elif os_family == "MacOS": - self.service_name = "com.apple.AirPlayXPCHelper" - elif salt.utils.platform.is_windows(): - self.service_name = "Spooler" - - self.pre_srv_status = self.run_function("service.status", [self.service_name]) - self.pre_srv_enabled = ( - True - if self.service_name in self.run_function("service.get_enabled") - else False - ) - - if ( - salt.utils.path.which(cmd_name) is None - and not salt.utils.platform.is_windows() - ): - self.skipTest("{} is not installed".format(cmd_name)) - - def tearDown(self): - post_srv_status = self.run_function("service.status", [self.service_name]) - post_srv_enabled = ( - True - if self.service_name in self.run_function("service.get_enabled") - else False - ) - - if post_srv_status != self.pre_srv_status: - if self.pre_srv_status: - self.run_function("service.enable", [self.service_name]) - else: - self.run_function("service.disable", [self.service_name]) - - if post_srv_enabled != self.pre_srv_enabled: - if self.pre_srv_enabled: - self.run_function("service.enable", [self.service_name]) - else: - self.run_function("service.disable", [self.service_name]) - del self.service_name - - @pytest.mark.flaky(max_runs=4) - @pytest.mark.slow_test - def test_service_status_running(self): - """ - test service.status execution module - when service is running - """ - self.run_function("service.start", [self.service_name]) - check_service = self.run_function("service.status", [self.service_name]) - self.assertTrue(check_service) - - @pytest.mark.slow_test - def test_service_status_dead(self): - """ - test service.status execution module - when service is dead - """ - self.run_function("service.stop", [self.service_name]) - check_service = self.run_function("service.status", [self.service_name]) - self.assertFalse(check_service) - - @pytest.mark.slow_test - def test_service_restart(self): - """ - test service.restart - """ - self.assertTrue(self.run_function("service.restart", [self.service_name])) - - @pytest.mark.slow_test - def test_service_enable(self): - """ - test service.get_enabled and service.enable module - """ - # disable service before test - self.assertTrue(self.run_function("service.disable", [self.service_name])) - - self.assertTrue(self.run_function("service.enable", [self.service_name])) - self.assertIn(self.service_name, self.run_function("service.get_enabled")) - - @pytest.mark.slow_test - def test_service_disable(self): - """ - test service.get_disabled and service.disable module - """ - # enable service before test - self.assertTrue(self.run_function("service.enable", [self.service_name])) - - self.assertTrue(self.run_function("service.disable", [self.service_name])) - if salt.utils.platform.is_darwin(): - self.assertTrue(self.run_function("service.disabled", [self.service_name])) - else: - self.assertIn(self.service_name, self.run_function("service.get_disabled")) - - @pytest.mark.slow_test - def test_service_disable_doesnot_exist(self): - """ - test service.get_disabled and service.disable module - when service name does not exist - """ - # enable service before test - srv_name = "doesnotexist" - enable = self.run_function("service.enable", [srv_name]) - systemd = salt.utils.systemd.booted() - - # check service was not enabled - try: - self.assertFalse(enable) - except AssertionError: - self.assertIn("ERROR", enable) - - # check service was not disabled - if ( - tuple( - self.run_function("grains.item", ["osrelease_info"])["osrelease_info"] - ) - == (14, 0o4) - and not systemd - ): - # currently upstart does not have a mechanism to report if disabling a service fails if does not exist - self.assertTrue(self.run_function("service.disable", [srv_name])) - elif ( - self.run_function("grains.item", ["os"])["os"] == "Debian" - and self.run_function("grains.item", ["osmajorrelease"])["osmajorrelease"] - < 9 - and systemd - ): - # currently disabling a service via systemd that does not exist - # on Debian 8 results in a True return code - self.assertTrue(self.run_function("service.disable", [srv_name])) - else: - try: - disable = self.run_function("service.disable", [srv_name]) - self.assertFalse(disable) - except AssertionError: - self.assertTrue("error" in disable.lower()) - - if salt.utils.platform.is_darwin(): - self.assertEqual( - self.run_function("service.disabled", [srv_name]), - "ERROR: Service not found: {}".format(srv_name), - ) - else: - self.assertNotIn(srv_name, self.run_function("service.get_disabled")) - - @pytest.mark.skip_unless_on_windows - @pytest.mark.slow_test - def test_service_get_service_name(self): - """ - test service.get_service_name - """ - ret = self.run_function("service.get_service_name") - self.assertIn(self.service_name, ret.values()) diff --git a/tests/pytests/integration/modules/test_service.py b/tests/pytests/integration/modules/test_service.py new file mode 100644 index 00000000000..5a7115fffa2 --- /dev/null +++ b/tests/pytests/integration/modules/test_service.py @@ -0,0 +1,185 @@ +import os + +import pytest + +import salt.utils.path +import salt.utils.platform +import salt.utils.systemd + +pytestmark = [ + pytest.mark.windows_whitelisted, + pytest.mark.destructive_test, + pytest.mark.slow_test, +] + + +@pytest.fixture +def service_name(grains, salt_cli, salt_minion): + # For local testing purposes + env_name = os.environ.get("SALT_INTEGRATION_TEST_SERVICE_NAME") + if env_name is not None: + return env_name + + service_name = "cron" + cmd_name = "crontab" + os_family = grains["os_family"] + is_systemd = grains["systemd"] + if os_family == "RedHat": + service_name = "crond" + elif os_family == "Arch": + service_name = "sshd" + cmd_name = "systemctl" + elif os_family == "MacOS": + service_name = "com.apple.AirPlayXPCHelper" + elif os_family == "Windows": + service_name = "Spooler" + + if os_family != "Windows" and salt.utils.path.which(cmd_name) is None: + pytest.skip("{} is not installed".format(cmd_name)) + + if is_systemd and salt_cli.run("service.offline", minion_tgt=salt_minion.id): + pytest.skip("systemd is OFFLINE") + + return service_name + + +@pytest.fixture(autouse=True) +def setup_service(service_name, salt_cli, salt_minion): + pre_srv_status = salt_cli.run("service.status", minion_tgt=salt_minion.id).data + pre_srv_enabled = ( + service_name + in salt_cli.run("service.get_enabled", minion_tgt=salt_minion.id).data + ) + + yield pre_srv_status + + post_srv_status = salt_cli.run("service.status", minion_tgt=salt_minion.id).data + post_srv_enabled = ( + service_name + in salt_cli.run("service.get_enabled", minion_tgt=salt_minion.id).data + ) + + if post_srv_status != pre_srv_status: + if pre_srv_status: + salt_cli.run("service.enable", service_name, minion_tgt=salt_minion.id) + else: + salt_cli.run("service.disable", service_name, minion_tgt=salt_minion.id) + + if post_srv_enabled != pre_srv_enabled: + if pre_srv_enabled: + salt_cli.run("service.enable", service_name, minion_tgt=salt_minion.id) + else: + salt_cli.run("service.disable", service_name, minion_tgt=salt_minion.id) + + +@pytest.mark.flaky(max_runs=4) +def test_service_status_running(salt_cli, salt_minion, service_name): + """ + test service.status execution module + when service is running + """ + salt_cli.run("service.start", service_name, minion_tgt=salt_minion.id) + check_service = salt_cli.run( + "service.status", service_name, minion_tgt=salt_minion.id + ).data + assert check_service + + +def test_service_status_dead(salt_cli, salt_minion, service_name): + """ + test service.status execution module + when service is dead + """ + salt_cli.run("service.stop", service_name, minion_tgt=salt_minion.id) + check_service = salt_cli.run( + "service.status", service_name, minion_tgt=salt_minion.id + ).data + assert not check_service + + +def test_service_restart(salt_cli, salt_minion, service_name): + """ + test service.restart + """ + assert salt_cli.run("service.stop", service_name, minion_tgt=salt_minion.id).data + + +def test_service_enable(salt_cli, salt_minion, service_name): + """ + test service.get_enabled and service.enable module + """ + # disable service before test + assert salt_cli.run("service.disable", service_name, minion_tgt=salt_minion.id).data + + assert salt_cli.run("service.enable", service_name, minion_tgt=salt_minion.id).data + assert ( + service_name + in salt_cli.run("service.get_enabled", minion_tgt=salt_minion.id).data + ) + + +def test_service_disable(salt_cli, salt_minion, service_name): + """ + test service.get_disabled and service.disable module + """ + # enable service before test + assert salt_cli.run("service.enable", service_name, minion_tgt=salt_minion.id).data + + assert salt_cli.run("service.disable", service_name, minion_tgt=salt_minion.id).data + if salt.utils.platform.is_darwin(): + assert salt_cli.run( + "service.disabled", service_name, minion_tgt=salt_minion.id + ).data + else: + assert ( + service_name + in salt_cli.run("service.get_disabled", minion_tgt=salt_minion.id).data + ) + + +def test_service_disable_doesnot_exist(salt_cli, salt_minion): + """ + test service.get_disabled and service.disable module + when service name does not exist + """ + # enable service before test + srv_name = "doesnotexist" + enable = salt_cli.run("service.enable", srv_name, minion_tgt=salt_minion.id).data + systemd = salt.utils.systemd.booted() + + # check service was not enabled + try: + assert not enable + except AssertionError: + assert "error" in enable.lower() + + else: + try: + disable = salt_cli.run( + "service.disable", srv_name, minion_tgt=salt_minion.id + ).data + assert not disable + except AssertionError: + assert "error" in disable.lower() + + if salt.utils.platform.is_darwin(): + assert ( + "ERROR: Service not found: {}".format(srv_name) + in salt_cli.run( + "service.disabled", srv_name, minion_tgt=salt_minion.id + ).stdout + ) + else: + assert ( + srv_name + not in salt_cli.run("service.get_disabled", minion_tgt=salt_minion.id).data + ) + + +@pytest.mark.skip_unless_on_windows +def test_service_get_service_name(salt_cli, salt_minion, service_name): + """ + test service.get_service_name + """ + ret = salt_cli.run("service.get_service_name", minion_tgt=salt_minion.id).data + assert service_name in ret.data.values() diff --git a/tests/pytests/integration/states/test_service.py b/tests/pytests/integration/states/test_service.py index 2718be3cc45..b68afa856a5 100644 --- a/tests/pytests/integration/states/test_service.py +++ b/tests/pytests/integration/states/test_service.py @@ -9,9 +9,6 @@ import pytest import salt.utils.path import salt.utils.platform -INIT_DELAY = 5 - - pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.destructive_test, @@ -19,6 +16,7 @@ pytestmark = [ ] +INIT_DELAY = 5 STOPPED = False RUNNING = True @@ -26,7 +24,7 @@ RUNNING = True @pytest.fixture def service_name(grains, salt_cli, salt_minion): # For local testing purposes - env_name = os.environ.get("SALT_SERVICE_STATE_TEST_SERVICE") + env_name = os.environ.get("SALT_INTEGRATION_TEST_SERVICE_NAME") if env_name is not None: return env_name @@ -70,45 +68,6 @@ def setup_service(service_name, salt_cli, salt_minion): salt_cli.run("service.disable", service_name, minion_tgt=salt_minion.id) -# def setUp(self): -# self.service_name = "cron" -# cmd_name = "crontab" -# os_family = self.run_function("grains.get", ["os_family"]) -# os_release = self.run_function("grains.get", ["osrelease"]) -# is_systemd = self.run_function("grains.get", ["systemd"]) -# self.stopped = False -# self.running = True -# if os_family == "RedHat": -# self.service_name = "crond" -# elif os_family == "Arch": -# self.service_name = "sshd" -# cmd_name = "systemctl" -# elif os_family == "MacOS": -# self.service_name = "com.apple.AirPlayXPCHelper" -# elif os_family == "Windows": -# self.service_name = "Spooler" - -# self.pre_srv_enabled = ( -# True -# if self.service_name in self.run_function("service.get_enabled") -# else False -# ) -# self.post_srv_disable = False -# if not self.pre_srv_enabled: -# self.run_function("service.enable", name=self.service_name) -# self.post_srv_disable = True - -# if os_family != "Windows" and salt.utils.path.which(cmd_name) is None: -# self.skipTest("{} is not installed".format(cmd_name)) - -# if is_systemd and self.run_function("service.offline"): -# self.skipTest("systemd is OFFLINE") - -# def tearDown(self): -# if self.post_srv_disable: -# self.run_function("service.disable", name=self.service_name) - - def check_service_status(exp_return, salt_cli, salt_minion, service_name): """ helper method to check status of service From b1fe70ed098842e26c079535cff543631c0a60ce Mon Sep 17 00:00:00 2001 From: MKLeb Date: Fri, 30 Jun 2023 17:52:11 -0400 Subject: [PATCH 33/46] Use `.get()` on grains fixture --- tests/pytests/integration/modules/test_service.py | 4 ++-- tests/pytests/integration/states/test_service.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/pytests/integration/modules/test_service.py b/tests/pytests/integration/modules/test_service.py index 5a7115fffa2..1b4f75a2418 100644 --- a/tests/pytests/integration/modules/test_service.py +++ b/tests/pytests/integration/modules/test_service.py @@ -22,8 +22,8 @@ def service_name(grains, salt_cli, salt_minion): service_name = "cron" cmd_name = "crontab" - os_family = grains["os_family"] - is_systemd = grains["systemd"] + os_family = grains.get("os_family") + is_systemd = grains.get("systemd") if os_family == "RedHat": service_name = "crond" elif os_family == "Arch": diff --git a/tests/pytests/integration/states/test_service.py b/tests/pytests/integration/states/test_service.py index b68afa856a5..c6ac99d7306 100644 --- a/tests/pytests/integration/states/test_service.py +++ b/tests/pytests/integration/states/test_service.py @@ -30,8 +30,8 @@ def service_name(grains, salt_cli, salt_minion): service_name = "cron" cmd_name = "crontab" - os_family = grains["os_family"] - is_systemd = grains["systemd"] + os_family = grains.get("os_family") + is_systemd = grains.get("systemd") if os_family == "RedHat": service_name = "crond" elif os_family == "Arch": From ed299d9d7010b4d75585a26a399acb1a0a60c419 Mon Sep 17 00:00:00 2001 From: MKLeb Date: Thu, 13 Jul 2023 15:10:16 -0400 Subject: [PATCH 34/46] Move the service module and state integration tests to be functional tests --- tests/filename_map.yml | 4 +- .../functional/modules/test_service.py | 157 +++++++++++++++ .../pytests/functional/states/test_service.py | 120 ++++++++++++ .../integration/modules/test_service.py | 185 ------------------ .../integration/states/test_service.py | 143 -------------- 5 files changed, 279 insertions(+), 330 deletions(-) create mode 100644 tests/pytests/functional/modules/test_service.py create mode 100644 tests/pytests/functional/states/test_service.py delete mode 100644 tests/pytests/integration/modules/test_service.py delete mode 100644 tests/pytests/integration/states/test_service.py diff --git a/tests/filename_map.yml b/tests/filename_map.yml index caa5e472144..6e5da60df43 100644 --- a/tests/filename_map.yml +++ b/tests/filename_map.yml @@ -30,8 +30,8 @@ salt/modules/(aix_group|groupadd|mac_group|pw_group|solaris_group|win_groupadd)\ salt/modules/(debian_service|freebsdservice|gentoo_service|launchctl_service|mac_service|netbsdservice|openbsdrcctl_service|openbsdservice|rh_service|runit|linux_service|smf_service|systemd_service|upstart_service|win_service)\.py: - pytests.unit.states.test_service - - pytests.integration.modules.test_service - - pytests.integration.states.test_service + - pytests.functional.modules.test_service + - pytests.functional.states.test_service salt/modules/ansiblegate.py: diff --git a/tests/pytests/functional/modules/test_service.py b/tests/pytests/functional/modules/test_service.py new file mode 100644 index 00000000000..234da77a95b --- /dev/null +++ b/tests/pytests/functional/modules/test_service.py @@ -0,0 +1,157 @@ +import os + +import pytest + +import salt.utils.path +import salt.utils.platform +import salt.utils.systemd +from salt.exceptions import CommandExecutionError + +pytestmark = [ + pytest.mark.windows_whitelisted, + pytest.mark.destructive_test, + pytest.mark.slow_test, +] + + +@pytest.fixture +def service_name(grains, modules): + # For local testing purposes + env_name = os.environ.get("SALT_FUNCTIONAL_TEST_SERVICE_NAME") + if env_name is not None: + return env_name + + service_name = "cron" + cmd_name = "crontab" + os_family = grains.get("os_family") + is_systemd = grains.get("systemd") + if os_family == "RedHat": + service_name = "crond" + elif os_family == "Arch": + service_name = "sshd" + cmd_name = "systemctl" + elif os_family == "MacOS": + service_name = "com.apple.AirPlayXPCHelper" + elif os_family == "Windows": + service_name = "Spooler" + + if os_family != "Windows" and salt.utils.path.which(cmd_name) is None: + pytest.skip("{} is not installed".format(cmd_name)) + + if is_systemd and modules.service.offline(): + pytest.skip("systemd is OFFLINE") + + return service_name + + +@pytest.fixture(autouse=True) +def setup_service(service_name, modules): + pre_srv_status = modules.service.status(service_name) + pre_srv_enabled = service_name in modules.service.get_enabled() + + yield pre_srv_status + + post_srv_status = modules.service.status(service_name) + post_srv_enabled = service_name in modules.service.get_enabled() + + if post_srv_status != pre_srv_status: + if pre_srv_status: + modules.service.enable(service_name) + else: + modules.service.disable(service_name) + + if post_srv_enabled != pre_srv_enabled: + if pre_srv_enabled: + modules.service.enable(service_name) + else: + modules.service.disable(service_name) + + +@pytest.mark.flaky(max_runs=4) +def test_service_status_running(modules, service_name): + """ + test service.status execution module + when service is running + """ + modules.service.start(service_name) + check_service = modules.service.status(service_name) + assert check_service + + +def test_service_status_dead(modules, service_name): + """ + test service.status execution module + when service is dead + """ + modules.service.stop(service_name) + check_service = modules.service.status(service_name) + assert not check_service + + +def test_service_restart(modules, service_name): + """ + test service.restart + """ + assert modules.service.stop(service_name) + + +def test_service_enable(modules, service_name): + """ + test service.get_enabled and service.enable module + """ + # disable service before test + assert modules.service.disable(service_name) + + assert modules.service.enable(service_name) + assert service_name in modules.service.get_enabled() + + +def test_service_disable(modules, service_name): + """ + test service.get_disabled and service.disable module + """ + # enable service before test + assert modules.service.enable(service_name) + + assert modules.service.disable(service_name) + if salt.utils.platform.is_darwin(): + assert modules.service.disabled(service_name) + else: + assert service_name in modules.service.get_disabled() + + +def test_service_disable_doesnot_exist(modules): + """ + test service.get_disabled and service.disable module + when service name does not exist + """ + # enable service before test + srv_name = "doesnotexist" + try: + enable = modules.service.enable(srv_name) + assert not enable + except CommandExecutionError as exc: + assert srv_name in exc.error + + try: + disable = modules.service.disable(srv_name) + assert not disable + except CommandExecutionError as exc: + assert srv_name in exc.error + + if salt.utils.platform.is_darwin(): + with pytest.raises( + CommandExecutionError, match=f"Service not found: {srv_name}" + ): + modules.service.disabled(srv_name) + else: + assert srv_name not in modules.service.get_disabled() + + +@pytest.mark.skip_unless_on_windows +def test_service_get_service_name(modules, service_name): + """ + test service.get_service_name + """ + ret = modules.service.get_service_name() + assert service_name in ret.data.values() diff --git a/tests/pytests/functional/states/test_service.py b/tests/pytests/functional/states/test_service.py new file mode 100644 index 00000000000..8d577b3d97f --- /dev/null +++ b/tests/pytests/functional/states/test_service.py @@ -0,0 +1,120 @@ +""" +Tests for the service state +""" + +import os + +import pytest + +import salt.utils.path +import salt.utils.platform + +pytestmark = [ + pytest.mark.windows_whitelisted, + pytest.mark.destructive_test, + pytest.mark.slow_test, +] + + +INIT_DELAY = 5 +STOPPED = False +RUNNING = True + + +@pytest.fixture +def service_name(grains, modules): + # For local testing purposes + env_name = os.environ.get("SALT_FUNCTIONAL_TEST_SERVICE_NAME") + if env_name is not None: + return env_name + + service_name = "cron" + cmd_name = "crontab" + os_family = grains.get("os_family") + is_systemd = grains.get("systemd") + if os_family == "RedHat": + service_name = "crond" + elif os_family == "Arch": + service_name = "sshd" + cmd_name = "systemctl" + elif os_family == "MacOS": + service_name = "com.apple.AirPlayXPCHelper" + elif os_family == "Windows": + service_name = "Spooler" + + if os_family != "Windows" and salt.utils.path.which(cmd_name) is None: + pytest.skip("{} is not installed".format(cmd_name)) + + if is_systemd and modules.service.offline(): + pytest.skip("systemd is OFFLINE") + + return service_name + + +@pytest.fixture(autouse=True) +def setup_service(service_name, modules): + pre_srv_enabled = True if service_name in modules.service.get_enabled() else False + post_srv_disable = False + if not pre_srv_enabled: + modules.service.enable(service_name) + post_srv_disable = True + yield post_srv_disable + if post_srv_disable: + modules.service.disable(service_name) + + +def check_service_status(exp_return, modules, service_name): + """ + helper method to check status of service + """ + check_status = modules.service.status(service_name) + + if check_status is not exp_return: + pytest.fail("status of service is not returning correctly") + + +@pytest.mark.slow_test +def test_service_running(service_name, modules, states): + """ + test service.running state module + """ + if modules.service.status(service_name): + stop_service = modules.service.stop(service_name) + assert stop_service is True + check_service_status(STOPPED, modules, service_name) + + if salt.utils.platform.is_darwin(): + # make sure the service is enabled on macosx + enable = modules.service.enable(service_name) + + start_service = states.service.running(service_name) + assert start_service.full_return["result"] is True + check_service_status(RUNNING, modules, service_name) + + +@pytest.mark.slow_test +def test_service_dead(service_name, modules, states): + """ + test service.dead state module + """ + start_service = states.service.running(service_name) + assert start_service.full_return["result"] is True + check_service_status(RUNNING, modules, service_name) + + ret = states.service.dead(service_name) + assert ret.full_return["result"] is True + check_service_status(STOPPED, modules, service_name) + + +@pytest.mark.slow_test +def test_service_dead_init_delay(service_name, modules, states): + """ + test service.dead state module + """ + start_service = states.service.running(service_name) + assert start_service.full_return["result"] is True + check_service_status(RUNNING, modules, service_name) + + ret = states.service.dead(service_name, init_delay=INIT_DELAY) + assert ret.full_return["result"] is True + check_service_status(STOPPED, modules, service_name) diff --git a/tests/pytests/integration/modules/test_service.py b/tests/pytests/integration/modules/test_service.py deleted file mode 100644 index 1b4f75a2418..00000000000 --- a/tests/pytests/integration/modules/test_service.py +++ /dev/null @@ -1,185 +0,0 @@ -import os - -import pytest - -import salt.utils.path -import salt.utils.platform -import salt.utils.systemd - -pytestmark = [ - pytest.mark.windows_whitelisted, - pytest.mark.destructive_test, - pytest.mark.slow_test, -] - - -@pytest.fixture -def service_name(grains, salt_cli, salt_minion): - # For local testing purposes - env_name = os.environ.get("SALT_INTEGRATION_TEST_SERVICE_NAME") - if env_name is not None: - return env_name - - service_name = "cron" - cmd_name = "crontab" - os_family = grains.get("os_family") - is_systemd = grains.get("systemd") - if os_family == "RedHat": - service_name = "crond" - elif os_family == "Arch": - service_name = "sshd" - cmd_name = "systemctl" - elif os_family == "MacOS": - service_name = "com.apple.AirPlayXPCHelper" - elif os_family == "Windows": - service_name = "Spooler" - - if os_family != "Windows" and salt.utils.path.which(cmd_name) is None: - pytest.skip("{} is not installed".format(cmd_name)) - - if is_systemd and salt_cli.run("service.offline", minion_tgt=salt_minion.id): - pytest.skip("systemd is OFFLINE") - - return service_name - - -@pytest.fixture(autouse=True) -def setup_service(service_name, salt_cli, salt_minion): - pre_srv_status = salt_cli.run("service.status", minion_tgt=salt_minion.id).data - pre_srv_enabled = ( - service_name - in salt_cli.run("service.get_enabled", minion_tgt=salt_minion.id).data - ) - - yield pre_srv_status - - post_srv_status = salt_cli.run("service.status", minion_tgt=salt_minion.id).data - post_srv_enabled = ( - service_name - in salt_cli.run("service.get_enabled", minion_tgt=salt_minion.id).data - ) - - if post_srv_status != pre_srv_status: - if pre_srv_status: - salt_cli.run("service.enable", service_name, minion_tgt=salt_minion.id) - else: - salt_cli.run("service.disable", service_name, minion_tgt=salt_minion.id) - - if post_srv_enabled != pre_srv_enabled: - if pre_srv_enabled: - salt_cli.run("service.enable", service_name, minion_tgt=salt_minion.id) - else: - salt_cli.run("service.disable", service_name, minion_tgt=salt_minion.id) - - -@pytest.mark.flaky(max_runs=4) -def test_service_status_running(salt_cli, salt_minion, service_name): - """ - test service.status execution module - when service is running - """ - salt_cli.run("service.start", service_name, minion_tgt=salt_minion.id) - check_service = salt_cli.run( - "service.status", service_name, minion_tgt=salt_minion.id - ).data - assert check_service - - -def test_service_status_dead(salt_cli, salt_minion, service_name): - """ - test service.status execution module - when service is dead - """ - salt_cli.run("service.stop", service_name, minion_tgt=salt_minion.id) - check_service = salt_cli.run( - "service.status", service_name, minion_tgt=salt_minion.id - ).data - assert not check_service - - -def test_service_restart(salt_cli, salt_minion, service_name): - """ - test service.restart - """ - assert salt_cli.run("service.stop", service_name, minion_tgt=salt_minion.id).data - - -def test_service_enable(salt_cli, salt_minion, service_name): - """ - test service.get_enabled and service.enable module - """ - # disable service before test - assert salt_cli.run("service.disable", service_name, minion_tgt=salt_minion.id).data - - assert salt_cli.run("service.enable", service_name, minion_tgt=salt_minion.id).data - assert ( - service_name - in salt_cli.run("service.get_enabled", minion_tgt=salt_minion.id).data - ) - - -def test_service_disable(salt_cli, salt_minion, service_name): - """ - test service.get_disabled and service.disable module - """ - # enable service before test - assert salt_cli.run("service.enable", service_name, minion_tgt=salt_minion.id).data - - assert salt_cli.run("service.disable", service_name, minion_tgt=salt_minion.id).data - if salt.utils.platform.is_darwin(): - assert salt_cli.run( - "service.disabled", service_name, minion_tgt=salt_minion.id - ).data - else: - assert ( - service_name - in salt_cli.run("service.get_disabled", minion_tgt=salt_minion.id).data - ) - - -def test_service_disable_doesnot_exist(salt_cli, salt_minion): - """ - test service.get_disabled and service.disable module - when service name does not exist - """ - # enable service before test - srv_name = "doesnotexist" - enable = salt_cli.run("service.enable", srv_name, minion_tgt=salt_minion.id).data - systemd = salt.utils.systemd.booted() - - # check service was not enabled - try: - assert not enable - except AssertionError: - assert "error" in enable.lower() - - else: - try: - disable = salt_cli.run( - "service.disable", srv_name, minion_tgt=salt_minion.id - ).data - assert not disable - except AssertionError: - assert "error" in disable.lower() - - if salt.utils.platform.is_darwin(): - assert ( - "ERROR: Service not found: {}".format(srv_name) - in salt_cli.run( - "service.disabled", srv_name, minion_tgt=salt_minion.id - ).stdout - ) - else: - assert ( - srv_name - not in salt_cli.run("service.get_disabled", minion_tgt=salt_minion.id).data - ) - - -@pytest.mark.skip_unless_on_windows -def test_service_get_service_name(salt_cli, salt_minion, service_name): - """ - test service.get_service_name - """ - ret = salt_cli.run("service.get_service_name", minion_tgt=salt_minion.id).data - assert service_name in ret.data.values() diff --git a/tests/pytests/integration/states/test_service.py b/tests/pytests/integration/states/test_service.py deleted file mode 100644 index c6ac99d7306..00000000000 --- a/tests/pytests/integration/states/test_service.py +++ /dev/null @@ -1,143 +0,0 @@ -""" -Tests for the service state -""" - -import os - -import pytest - -import salt.utils.path -import salt.utils.platform - -pytestmark = [ - pytest.mark.windows_whitelisted, - pytest.mark.destructive_test, - pytest.mark.slow_test, -] - - -INIT_DELAY = 5 -STOPPED = False -RUNNING = True - - -@pytest.fixture -def service_name(grains, salt_cli, salt_minion): - # For local testing purposes - env_name = os.environ.get("SALT_INTEGRATION_TEST_SERVICE_NAME") - if env_name is not None: - return env_name - - service_name = "cron" - cmd_name = "crontab" - os_family = grains.get("os_family") - is_systemd = grains.get("systemd") - if os_family == "RedHat": - service_name = "crond" - elif os_family == "Arch": - service_name = "sshd" - cmd_name = "systemctl" - elif os_family == "MacOS": - service_name = "com.apple.AirPlayXPCHelper" - elif os_family == "Windows": - service_name = "Spooler" - - if os_family != "Windows" and salt.utils.path.which(cmd_name) is None: - pytest.skip("{} is not installed".format(cmd_name)) - - if is_systemd and salt_cli.run("service.offline", minion_tgt=salt_minion.id): - pytest.skip("systemd is OFFLINE") - - return service_name - - -@pytest.fixture(autouse=True) -def setup_service(service_name, salt_cli, salt_minion): - pre_srv_enabled = ( - True - if service_name - in salt_cli.run("service.get_enabled", minion_tgt=salt_minion.id).stdout - else False - ) - post_srv_disable = False - if not pre_srv_enabled: - salt_cli.run("service.enable", service_name, minion_tgt=salt_minion.id) - post_srv_disable = True - yield post_srv_disable - if post_srv_disable: - salt_cli.run("service.disable", service_name, minion_tgt=salt_minion.id) - - -def check_service_status(exp_return, salt_cli, salt_minion, service_name): - """ - helper method to check status of service - """ - check_status = salt_cli.run( - "service.status", service_name, minion_tgt=salt_minion.id - ) - - if check_status.data is not exp_return: - pytest.fail("status of service is not returning correctly") - - -@pytest.mark.slow_test -def test_service_running(service_name, salt_minion, salt_cli): - """ - test service.running state module - """ - if salt_cli.run("service.status", service_name, minion_tgt=salt_minion.id): - stop_service = salt_cli.run( - "service.stop", service_name, minion_tgt=salt_minion.id - ) - assert stop_service.data is True - check_service_status(STOPPED, salt_cli, salt_minion, service_name) - - if salt.utils.platform.is_darwin(): - # make sure the service is enabled on macosx - enable = salt_cli.run("service.enable", service_name, minion_tgt=salt_minion.id) - - start_service = salt_cli.run( - "state.single", "service.running", service_name, minion_tgt=salt_minion.id - ) - assert next(iter(start_service.data.values()))["result"] is True - check_service_status(RUNNING, salt_cli, salt_minion, service_name) - - -@pytest.mark.slow_test -def test_service_dead(service_name, salt_cli, salt_minion): - """ - test service.dead state module - """ - start_service = salt_cli.run( - "state.single", "service.running", service_name, minion_tgt=salt_minion.id - ) - assert next(iter(start_service.data.values()))["result"] is True - check_service_status(RUNNING, salt_cli, salt_minion, service_name) - - ret = salt_cli.run( - "state.single", "service.dead", service_name, minion_tgt=salt_minion.id - ) - assert next(iter(ret.data.values()))["result"] is True - check_service_status(STOPPED, salt_cli, salt_minion, service_name) - - -@pytest.mark.slow_test -def test_service_dead_init_delay(service_name, salt_cli, salt_minion): - """ - test service.dead state module with init_delay arg - """ - start_service = salt_cli.run( - "state.single", "service.running", service_name, minion_tgt=salt_minion.id - ) - assert next(iter(start_service.data.values()))["result"] is True - check_service_status(RUNNING, salt_cli, salt_minion, service_name) - - ret = salt_cli.run( - "state.single", - "service.dead", - service_name, - init_delay=INIT_DELAY, - minion_tgt=salt_minion.id, - ) - assert next(iter(ret.data.values()))["result"] is True - check_service_status(STOPPED, salt_cli, salt_minion, service_name) From 65a6c47c8147b8b9b5180caeced5061e47302e25 Mon Sep 17 00:00:00 2001 From: MKLeb Date: Fri, 14 Jul 2023 09:41:08 -0400 Subject: [PATCH 35/46] Fix some failing systemd-based tests and remove old `data` reference --- tests/pytests/functional/modules/test_service.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/pytests/functional/modules/test_service.py b/tests/pytests/functional/modules/test_service.py index 234da77a95b..e5e9f47b11b 100644 --- a/tests/pytests/functional/modules/test_service.py +++ b/tests/pytests/functional/modules/test_service.py @@ -137,7 +137,7 @@ def test_service_disable_doesnot_exist(modules): disable = modules.service.disable(srv_name) assert not disable except CommandExecutionError as exc: - assert srv_name in exc.error + assert srv_name in exc.error or "no such file or directory" in exc.error.lower() if salt.utils.platform.is_darwin(): with pytest.raises( @@ -154,4 +154,4 @@ def test_service_get_service_name(modules, service_name): test service.get_service_name """ ret = modules.service.get_service_name() - assert service_name in ret.data.values() + assert service_name in ret.values() From 04a8b334ad04fff678bad37cb69a46693a287671 Mon Sep 17 00:00:00 2001 From: MKLeb Date: Fri, 14 Jul 2023 16:21:49 -0400 Subject: [PATCH 36/46] Also check for `no such file or directory` during the enablement check --- tests/pytests/functional/modules/test_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pytests/functional/modules/test_service.py b/tests/pytests/functional/modules/test_service.py index e5e9f47b11b..64c29a5b631 100644 --- a/tests/pytests/functional/modules/test_service.py +++ b/tests/pytests/functional/modules/test_service.py @@ -131,7 +131,7 @@ def test_service_disable_doesnot_exist(modules): enable = modules.service.enable(srv_name) assert not enable except CommandExecutionError as exc: - assert srv_name in exc.error + assert srv_name in exc.error or "no such file or directory" in exc.error.lower() try: disable = modules.service.disable(srv_name) From 2a33abaf6cdf38df2c6e929793bb0f1cbda7bdcf Mon Sep 17 00:00:00 2001 From: MKLeb Date: Mon, 17 Jul 2023 12:47:19 -0400 Subject: [PATCH 37/46] Remove `flaky` decorator from `test_service_status_running` --- tests/pytests/functional/modules/test_service.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/pytests/functional/modules/test_service.py b/tests/pytests/functional/modules/test_service.py index 64c29a5b631..8f8b1fc2349 100644 --- a/tests/pytests/functional/modules/test_service.py +++ b/tests/pytests/functional/modules/test_service.py @@ -67,7 +67,6 @@ def setup_service(service_name, modules): modules.service.disable(service_name) -@pytest.mark.flaky(max_runs=4) def test_service_status_running(modules, service_name): """ test service.status execution module From a40d5afcac510dded33feeccd05e70f39ad8d3a1 Mon Sep 17 00:00:00 2001 From: MKLeb Date: Mon, 17 Jul 2023 12:50:41 -0400 Subject: [PATCH 38/46] Switch to `try/finally` blocks in `setup_service` fixtures --- .../functional/modules/test_service.py | 29 ++++++++++--------- .../pytests/functional/states/test_service.py | 8 +++-- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/tests/pytests/functional/modules/test_service.py b/tests/pytests/functional/modules/test_service.py index 8f8b1fc2349..8001eb45e43 100644 --- a/tests/pytests/functional/modules/test_service.py +++ b/tests/pytests/functional/modules/test_service.py @@ -49,22 +49,23 @@ def setup_service(service_name, modules): pre_srv_status = modules.service.status(service_name) pre_srv_enabled = service_name in modules.service.get_enabled() - yield pre_srv_status + try: + yield pre_srv_status + finally: + post_srv_status = modules.service.status(service_name) + post_srv_enabled = service_name in modules.service.get_enabled() - post_srv_status = modules.service.status(service_name) - post_srv_enabled = service_name in modules.service.get_enabled() + if post_srv_status != pre_srv_status: + if pre_srv_status: + modules.service.enable(service_name) + else: + modules.service.disable(service_name) - if post_srv_status != pre_srv_status: - if pre_srv_status: - modules.service.enable(service_name) - else: - modules.service.disable(service_name) - - if post_srv_enabled != pre_srv_enabled: - if pre_srv_enabled: - modules.service.enable(service_name) - else: - modules.service.disable(service_name) + if post_srv_enabled != pre_srv_enabled: + if pre_srv_enabled: + modules.service.enable(service_name) + else: + modules.service.disable(service_name) def test_service_status_running(modules, service_name): diff --git a/tests/pytests/functional/states/test_service.py b/tests/pytests/functional/states/test_service.py index 8d577b3d97f..82006a22a1f 100644 --- a/tests/pytests/functional/states/test_service.py +++ b/tests/pytests/functional/states/test_service.py @@ -58,9 +58,11 @@ def setup_service(service_name, modules): if not pre_srv_enabled: modules.service.enable(service_name) post_srv_disable = True - yield post_srv_disable - if post_srv_disable: - modules.service.disable(service_name) + try: + yield post_srv_disable + finally: + if post_srv_disable: + modules.service.disable(service_name) def check_service_status(exp_return, modules, service_name): From 4d6ac22edea37f213fad2caa4417bc34a023047d Mon Sep 17 00:00:00 2001 From: MKLeb Date: Wed, 19 Jul 2023 10:21:28 -0400 Subject: [PATCH 39/46] Make sure the service is in the state it started at after running the service module tests --- .../functional/modules/test_service.py | 4 +-- .../pytests/functional/states/test_service.py | 26 +++++++++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/tests/pytests/functional/modules/test_service.py b/tests/pytests/functional/modules/test_service.py index 8001eb45e43..51ce7f1cc0b 100644 --- a/tests/pytests/functional/modules/test_service.py +++ b/tests/pytests/functional/modules/test_service.py @@ -57,9 +57,9 @@ def setup_service(service_name, modules): if post_srv_status != pre_srv_status: if pre_srv_status: - modules.service.enable(service_name) + modules.service.start(service_name) else: - modules.service.disable(service_name) + modules.service.stop(service_name) if post_srv_enabled != pre_srv_enabled: if pre_srv_enabled: diff --git a/tests/pytests/functional/states/test_service.py b/tests/pytests/functional/states/test_service.py index 82006a22a1f..a1e9673653b 100644 --- a/tests/pytests/functional/states/test_service.py +++ b/tests/pytests/functional/states/test_service.py @@ -53,16 +53,26 @@ def service_name(grains, modules): @pytest.fixture(autouse=True) def setup_service(service_name, modules): - pre_srv_enabled = True if service_name in modules.service.get_enabled() else False - post_srv_disable = False - if not pre_srv_enabled: - modules.service.enable(service_name) - post_srv_disable = True + pre_srv_status = modules.service.status(service_name) + pre_srv_enabled = service_name in modules.service.get_enabled() + try: - yield post_srv_disable + yield pre_srv_status finally: - if post_srv_disable: - modules.service.disable(service_name) + post_srv_status = modules.service.status(service_name) + post_srv_enabled = service_name in modules.service.get_enabled() + + if post_srv_status != pre_srv_status: + if pre_srv_status: + modules.service.start(service_name) + else: + modules.service.stop(service_name) + + if post_srv_enabled != pre_srv_enabled: + if pre_srv_enabled: + modules.service.enable(service_name) + else: + modules.service.disable(service_name) def check_service_status(exp_return, modules, service_name): From 5613db440811430d5610befbe952f75dffa52290 Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Sun, 16 Jul 2023 15:03:06 -0700 Subject: [PATCH 40/46] Clarify rejected_retry option docs --- doc/ref/configuration/minion.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ref/configuration/minion.rst b/doc/ref/configuration/minion.rst index 69c7afbde84..b614376d136 100644 --- a/doc/ref/configuration/minion.rst +++ b/doc/ref/configuration/minion.rst @@ -1197,8 +1197,8 @@ seconds each iteration. Default: ``False`` -If the master rejects the minion's public key, retry instead of exiting. -Rejected keys will be handled the same as waiting on acceptance. +If the master denies or rejects the minion's public key, retry instead of +exiting. These keys will be handled the same as waiting on acceptance. .. code-block:: yaml From 145a0ed6fcb8b85d867e682bf2c47239f0412f19 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Fri, 21 Jul 2023 10:14:13 +0100 Subject: [PATCH 41/46] Bump to `aiohttp==3.8.5` due to https://github.com/advisories/GHSA-45c4-8wx5-qw6w Signed-off-by: Pedro Algarvio --- changelog/64687.security.md | 1 + requirements/static/ci/py3.10/cloud.txt | 2 +- requirements/static/ci/py3.10/darwin.txt | 2 +- requirements/static/ci/py3.10/freebsd.txt | 2 +- requirements/static/ci/py3.10/lint.txt | 2 +- requirements/static/ci/py3.10/linux.txt | 2 +- requirements/static/ci/py3.10/windows.txt | 2 +- requirements/static/ci/py3.7/cloud.txt | 2 +- requirements/static/ci/py3.7/freebsd.txt | 2 +- requirements/static/ci/py3.7/lint.txt | 2 +- requirements/static/ci/py3.7/linux.txt | 2 +- requirements/static/ci/py3.7/windows.txt | 2 +- requirements/static/ci/py3.8/cloud.txt | 2 +- requirements/static/ci/py3.8/freebsd.txt | 2 +- requirements/static/ci/py3.8/lint.txt | 2 +- requirements/static/ci/py3.8/linux.txt | 2 +- requirements/static/ci/py3.8/windows.txt | 2 +- requirements/static/ci/py3.9/cloud.txt | 2 +- requirements/static/ci/py3.9/darwin.txt | 2 +- requirements/static/ci/py3.9/freebsd.txt | 2 +- requirements/static/ci/py3.9/lint.txt | 2 +- requirements/static/ci/py3.9/linux.txt | 2 +- requirements/static/ci/py3.9/windows.txt | 2 +- 23 files changed, 23 insertions(+), 22 deletions(-) create mode 100644 changelog/64687.security.md diff --git a/changelog/64687.security.md b/changelog/64687.security.md new file mode 100644 index 00000000000..5b227c33bb3 --- /dev/null +++ b/changelog/64687.security.md @@ -0,0 +1 @@ +Bump to `aiohttp==3.8.5` due to https://github.com/advisories/GHSA-45c4-8wx5-qw6w diff --git a/requirements/static/ci/py3.10/cloud.txt b/requirements/static/ci/py3.10/cloud.txt index 2af515324f4..b18ec4f09c0 100644 --- a/requirements/static/ci/py3.10/cloud.txt +++ b/requirements/static/ci/py3.10/cloud.txt @@ -8,7 +8,7 @@ adal==1.2.7 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.10/darwin.txt b/requirements/static/ci/py3.10/darwin.txt index 73f4def8791..c0975217c25 100644 --- a/requirements/static/ci/py3.10/darwin.txt +++ b/requirements/static/ci/py3.10/darwin.txt @@ -8,7 +8,7 @@ adal==1.2.5 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.10/freebsd.txt b/requirements/static/ci/py3.10/freebsd.txt index 3739dcb0e73..baaf1233d53 100644 --- a/requirements/static/ci/py3.10/freebsd.txt +++ b/requirements/static/ci/py3.10/freebsd.txt @@ -8,7 +8,7 @@ adal==1.2.5 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.10/lint.txt b/requirements/static/ci/py3.10/lint.txt index c88948c6d8a..dc2efbcb0f7 100644 --- a/requirements/static/ci/py3.10/lint.txt +++ b/requirements/static/ci/py3.10/lint.txt @@ -8,7 +8,7 @@ adal==1.2.7 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.10/linux.txt b/requirements/static/ci/py3.10/linux.txt index 9edac4588d2..973d015842a 100644 --- a/requirements/static/ci/py3.10/linux.txt +++ b/requirements/static/ci/py3.10/linux.txt @@ -8,7 +8,7 @@ adal==1.2.3 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.10/windows.txt b/requirements/static/ci/py3.10/windows.txt index ecccb3335b0..2417941f38e 100644 --- a/requirements/static/ci/py3.10/windows.txt +++ b/requirements/static/ci/py3.10/windows.txt @@ -4,7 +4,7 @@ # # pip-compile --output-file=requirements/static/ci/py3.10/windows.txt --pip-args='--constraint=requirements/static/pkg/py3.10/windows.txt' requirements/pytest.txt requirements/static/ci/common.in requirements/static/ci/windows.in requirements/static/pkg/windows.in requirements/windows.txt # -aiohttp==3.8.3 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.3.1 # via aiohttp diff --git a/requirements/static/ci/py3.7/cloud.txt b/requirements/static/ci/py3.7/cloud.txt index bbbabcd11fc..6eaf60aa529 100644 --- a/requirements/static/ci/py3.7/cloud.txt +++ b/requirements/static/ci/py3.7/cloud.txt @@ -8,7 +8,7 @@ adal==1.2.7 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.7/freebsd.txt b/requirements/static/ci/py3.7/freebsd.txt index 8a3346af2c3..cb2a33a878a 100644 --- a/requirements/static/ci/py3.7/freebsd.txt +++ b/requirements/static/ci/py3.7/freebsd.txt @@ -8,7 +8,7 @@ adal==1.2.5 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.7/lint.txt b/requirements/static/ci/py3.7/lint.txt index 28cff6fb6d6..84fb45bda87 100644 --- a/requirements/static/ci/py3.7/lint.txt +++ b/requirements/static/ci/py3.7/lint.txt @@ -8,7 +8,7 @@ adal==1.2.7 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.7/linux.txt b/requirements/static/ci/py3.7/linux.txt index f93050ab932..4572c8bdbf3 100644 --- a/requirements/static/ci/py3.7/linux.txt +++ b/requirements/static/ci/py3.7/linux.txt @@ -8,7 +8,7 @@ adal==1.2.3 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.7/windows.txt b/requirements/static/ci/py3.7/windows.txt index 1f67dcfba0c..8959a773789 100644 --- a/requirements/static/ci/py3.7/windows.txt +++ b/requirements/static/ci/py3.7/windows.txt @@ -4,7 +4,7 @@ # # pip-compile --output-file=requirements/static/ci/py3.7/windows.txt --pip-args='--constraint=requirements/static/pkg/py3.7/windows.txt' requirements/pytest.txt requirements/static/ci/common.in requirements/static/ci/windows.in requirements/static/pkg/windows.in requirements/windows.txt # -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.8/cloud.txt b/requirements/static/ci/py3.8/cloud.txt index bd0e08a58b1..0efdfc4ddb6 100644 --- a/requirements/static/ci/py3.8/cloud.txt +++ b/requirements/static/ci/py3.8/cloud.txt @@ -8,7 +8,7 @@ adal==1.2.7 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.8/freebsd.txt b/requirements/static/ci/py3.8/freebsd.txt index c5405765a61..5bc0834aa96 100644 --- a/requirements/static/ci/py3.8/freebsd.txt +++ b/requirements/static/ci/py3.8/freebsd.txt @@ -8,7 +8,7 @@ adal==1.2.5 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.8/lint.txt b/requirements/static/ci/py3.8/lint.txt index 6817761f343..75cae1cbec6 100644 --- a/requirements/static/ci/py3.8/lint.txt +++ b/requirements/static/ci/py3.8/lint.txt @@ -8,7 +8,7 @@ adal==1.2.7 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.8/linux.txt b/requirements/static/ci/py3.8/linux.txt index 71621406fc1..f9bf547397f 100644 --- a/requirements/static/ci/py3.8/linux.txt +++ b/requirements/static/ci/py3.8/linux.txt @@ -8,7 +8,7 @@ adal==1.2.3 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.8/windows.txt b/requirements/static/ci/py3.8/windows.txt index a4ab2b0e0c2..63b94d8153c 100644 --- a/requirements/static/ci/py3.8/windows.txt +++ b/requirements/static/ci/py3.8/windows.txt @@ -4,7 +4,7 @@ # # pip-compile --output-file=requirements/static/ci/py3.8/windows.txt --pip-args='--constraint=requirements/static/pkg/py3.8/windows.txt' requirements/pytest.txt requirements/static/ci/common.in requirements/static/ci/windows.in requirements/static/pkg/windows.in requirements/windows.txt # -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.9/cloud.txt b/requirements/static/ci/py3.9/cloud.txt index 0edf98cbeed..284da11446c 100644 --- a/requirements/static/ci/py3.9/cloud.txt +++ b/requirements/static/ci/py3.9/cloud.txt @@ -8,7 +8,7 @@ adal==1.2.7 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.9/darwin.txt b/requirements/static/ci/py3.9/darwin.txt index 26ad2584cd8..cd6ea9161f0 100644 --- a/requirements/static/ci/py3.9/darwin.txt +++ b/requirements/static/ci/py3.9/darwin.txt @@ -8,7 +8,7 @@ adal==1.2.5 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.9/freebsd.txt b/requirements/static/ci/py3.9/freebsd.txt index f86158df323..6a6eecc62de 100644 --- a/requirements/static/ci/py3.9/freebsd.txt +++ b/requirements/static/ci/py3.9/freebsd.txt @@ -8,7 +8,7 @@ adal==1.2.5 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.9/lint.txt b/requirements/static/ci/py3.9/lint.txt index 097b21c0876..0797e729902 100644 --- a/requirements/static/ci/py3.9/lint.txt +++ b/requirements/static/ci/py3.9/lint.txt @@ -8,7 +8,7 @@ adal==1.2.7 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.9/linux.txt b/requirements/static/ci/py3.9/linux.txt index 064f9fbac6e..24cd91c4204 100644 --- a/requirements/static/ci/py3.9/linux.txt +++ b/requirements/static/ci/py3.9/linux.txt @@ -8,7 +8,7 @@ adal==1.2.3 # via # azure-datalake-store # msrestazure -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp diff --git a/requirements/static/ci/py3.9/windows.txt b/requirements/static/ci/py3.9/windows.txt index d2c6aba824b..282303ad60b 100644 --- a/requirements/static/ci/py3.9/windows.txt +++ b/requirements/static/ci/py3.9/windows.txt @@ -4,7 +4,7 @@ # # pip-compile --output-file=requirements/static/ci/py3.9/windows.txt --pip-args='--constraint=requirements/static/pkg/py3.9/windows.txt' requirements/pytest.txt requirements/static/ci/common.in requirements/static/ci/windows.in requirements/static/pkg/windows.in requirements/windows.txt # -aiohttp==3.8.1 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.2.0 # via aiohttp From 4dd85f9fb6ba9e3b14dbfd559eb279f28d56d6c4 Mon Sep 17 00:00:00 2001 From: twangboy Date: Wed, 19 Jul 2023 13:40:50 -0600 Subject: [PATCH 42/46] Use search with choco v2+ --- salt/modules/chocolatey.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/salt/modules/chocolatey.py b/salt/modules/chocolatey.py index 06794946d55..ee6b48a031b 100644 --- a/salt/modules/chocolatey.py +++ b/salt/modules/chocolatey.py @@ -460,7 +460,11 @@ def list_( salt '*' chocolatey.list all_versions=True """ choc_path = _find_chocolatey() - cmd = [choc_path, "list"] + # https://docs.chocolatey.org/en-us/guides/upgrading-to-chocolatey-v2-v6 + if Version(chocolatey_version()) <= Version("2.0.0"): + cmd = [choc_path, "list"] + else: + cmd = [choc_path, "search"] if narrow: cmd.append(narrow) if salt.utils.data.is_true(all_versions): @@ -518,7 +522,11 @@ def list_webpi(): salt '*' chocolatey.list_webpi """ choc_path = _find_chocolatey() - cmd = [choc_path, "list", "--source", "webpi"] + # https://docs.chocolatey.org/en-us/guides/upgrading-to-chocolatey-v2-v6 + if Version(chocolatey_version()) <= Version("2.0.0"): + cmd = [choc_path, "list", "--source", "webpi"] + else: + cmd = [choc_path, "search", "--source", "webpi"] result = __salt__["cmd.run_all"](cmd, python_shell=False) if result["retcode"] != 0: @@ -543,7 +551,11 @@ def list_windowsfeatures(): salt '*' chocolatey.list_windowsfeatures """ choc_path = _find_chocolatey() - cmd = [choc_path, "list", "--source", "windowsfeatures"] + # https://docs.chocolatey.org/en-us/guides/upgrading-to-chocolatey-v2-v6 + if Version(chocolatey_version()) <= Version("2.0.0"): + cmd = [choc_path, "list", "--source", "windowsfeatures"] + else: + cmd = [choc_path, "search", "--source", "windowsfeatures"] result = __salt__["cmd.run_all"](cmd, python_shell=False) if result["retcode"] != 0: From 279e133643bd38d56d74ce05f41aed9b33eee298 Mon Sep 17 00:00:00 2001 From: twangboy Date: Wed, 19 Jul 2023 13:46:32 -0600 Subject: [PATCH 43/46] Add changelog --- changelog/64622.fixed.md | 1 + salt/modules/chocolatey.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 changelog/64622.fixed.md diff --git a/changelog/64622.fixed.md b/changelog/64622.fixed.md new file mode 100644 index 00000000000..e46dbeb0ff6 --- /dev/null +++ b/changelog/64622.fixed.md @@ -0,0 +1 @@ +Added support for Chocolatey 2.0.0+ diff --git a/salt/modules/chocolatey.py b/salt/modules/chocolatey.py index ee6b48a031b..2dab74da497 100644 --- a/salt/modules/chocolatey.py +++ b/salt/modules/chocolatey.py @@ -461,7 +461,7 @@ def list_( """ choc_path = _find_chocolatey() # https://docs.chocolatey.org/en-us/guides/upgrading-to-chocolatey-v2-v6 - if Version(chocolatey_version()) <= Version("2.0.0"): + if Version(chocolatey_version()) < Version("2.0.0"): cmd = [choc_path, "list"] else: cmd = [choc_path, "search"] @@ -523,7 +523,7 @@ def list_webpi(): """ choc_path = _find_chocolatey() # https://docs.chocolatey.org/en-us/guides/upgrading-to-chocolatey-v2-v6 - if Version(chocolatey_version()) <= Version("2.0.0"): + if Version(chocolatey_version()) < Version("2.0.0"): cmd = [choc_path, "list", "--source", "webpi"] else: cmd = [choc_path, "search", "--source", "webpi"] @@ -552,7 +552,7 @@ def list_windowsfeatures(): """ choc_path = _find_chocolatey() # https://docs.chocolatey.org/en-us/guides/upgrading-to-chocolatey-v2-v6 - if Version(chocolatey_version()) <= Version("2.0.0"): + if Version(chocolatey_version()) < Version("2.0.0"): cmd = [choc_path, "list", "--source", "windowsfeatures"] else: cmd = [choc_path, "search", "--source", "windowsfeatures"] From 4a4312159c3ae82aa3f347b0ee09b3f14dfc0137 Mon Sep 17 00:00:00 2001 From: twangboy Date: Thu, 20 Jul 2023 17:51:09 -0600 Subject: [PATCH 44/46] Add some unit tests --- tests/pytests/unit/modules/test_chocolatey.py | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/tests/pytests/unit/modules/test_chocolatey.py b/tests/pytests/unit/modules/test_chocolatey.py index c4b955321d1..ac553ceba63 100644 --- a/tests/pytests/unit/modules/test_chocolatey.py +++ b/tests/pytests/unit/modules/test_chocolatey.py @@ -262,3 +262,75 @@ def test_add_source(choco_path): "source_name", "source_location", priority="priority" ) cmd_run_all_mock.assert_called_with(expected_call, python_shell=False) + + +def test_list_pre_2_0_0(): + mock_version = MagicMock(return_value="1.2.1") + mock_find = MagicMock(return_value=choco_path) + mock_run = MagicMock(return_value={"stdout": "No packages", "retcode": 0}) + with patch.object(chocolatey, "chocolatey_version", mock_version), patch.object( + chocolatey, "_find_chocolatey", mock_find + ), patch.dict(chocolatey.__salt__, {"cmd.run_all": mock_run}): + chocolatey.list_() + expected_call = [choco_path, "list", "--limit-output"] + mock_run.assert_called_with(expected_call, python_shell=False) + + +def test_list_post_2_0_0(): + mock_version = MagicMock(return_value="2.0.1") + mock_find = MagicMock(return_value=choco_path) + mock_run = MagicMock(return_value={"stdout": "No packages", "retcode": 0}) + with patch.object(chocolatey, "chocolatey_version", mock_version), patch.object( + chocolatey, "_find_chocolatey", mock_find + ), patch.dict(chocolatey.__salt__, {"cmd.run_all": mock_run}): + chocolatey.list_() + expected_call = [choco_path, "search", "--limit-output"] + mock_run.assert_called_with(expected_call, python_shell=False) + + +def test_list_webpi_pre_2_0_0(): + mock_version = MagicMock(return_value="1.2.1") + mock_find = MagicMock(return_value=choco_path) + mock_run = MagicMock(return_value={"stdout": "No packages", "retcode": 0}) + with patch.object(chocolatey, "chocolatey_version", mock_version), patch.object( + chocolatey, "_find_chocolatey", mock_find + ), patch.dict(chocolatey.__salt__, {"cmd.run_all": mock_run}): + chocolatey.list_webpi() + expected_call = [choco_path, "list", "--source", "webpi"] + mock_run.assert_called_with(expected_call, python_shell=False) + + +def test_list_webpi_post_2_0_0(): + mock_version = MagicMock(return_value="2.0.1") + mock_find = MagicMock(return_value=choco_path) + mock_run = MagicMock(return_value={"stdout": "No packages", "retcode": 0}) + with patch.object(chocolatey, "chocolatey_version", mock_version), patch.object( + chocolatey, "_find_chocolatey", mock_find + ), patch.dict(chocolatey.__salt__, {"cmd.run_all": mock_run}): + chocolatey.list_webpi() + expected_call = [choco_path, "search", "--source", "webpi"] + mock_run.assert_called_with(expected_call, python_shell=False) + + +def test_list_windowsfeatures_pre_2_0_0(): + mock_version = MagicMock(return_value="1.2.1") + mock_find = MagicMock(return_value=choco_path) + mock_run = MagicMock(return_value={"stdout": "No packages", "retcode": 0}) + with patch.object(chocolatey, "chocolatey_version", mock_version), patch.object( + chocolatey, "_find_chocolatey", mock_find + ), patch.dict(chocolatey.__salt__, {"cmd.run_all": mock_run}): + chocolatey.list_windowsfeatures() + expected_call = [choco_path, "list", "--source", "windowsfeatures"] + mock_run.assert_called_with(expected_call, python_shell=False) + + +def test_list_windowsfeatures_post_2_0_0(): + mock_version = MagicMock(return_value="2.0.1") + mock_find = MagicMock(return_value=choco_path) + mock_run = MagicMock(return_value={"stdout": "No packages", "retcode": 0}) + with patch.object(chocolatey, "chocolatey_version", mock_version), patch.object( + chocolatey, "_find_chocolatey", mock_find + ), patch.dict(chocolatey.__salt__, {"cmd.run_all": mock_run}): + chocolatey.list_windowsfeatures() + expected_call = [choco_path, "search", "--source", "windowsfeatures"] + mock_run.assert_called_with(expected_call, python_shell=False) From c06f94523a22884a6440adc871548fe0a96fd73a Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Fri, 21 Jul 2023 18:16:37 +0100 Subject: [PATCH 45/46] Bump a few dependency versions that got downgraded on the merge forward Signed-off-by: Pedro Algarvio --- requirements/static/ci/py3.10/linux.txt | 2 +- requirements/static/ci/py3.11/darwin.txt | 2 +- requirements/static/ci/py3.11/freebsd.txt | 2 +- requirements/static/ci/py3.11/linux.txt | 2 +- requirements/static/ci/py3.8/linux.txt | 2 +- requirements/static/ci/py3.9/linux.txt | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/requirements/static/ci/py3.10/linux.txt b/requirements/static/ci/py3.10/linux.txt index 0f0faa86348..b7ab4f2d0f3 100644 --- a/requirements/static/ci/py3.10/linux.txt +++ b/requirements/static/ci/py3.10/linux.txt @@ -11,7 +11,7 @@ aiohttp==3.8.5 # aiohttp-retry # etcd3-py # twilio -aiosignal==1.2.0 +aiosignal==1.3.1 # via aiohttp ansible-core==2.15.0 # via ansible diff --git a/requirements/static/ci/py3.11/darwin.txt b/requirements/static/ci/py3.11/darwin.txt index a1159fe23b8..fd5deacb7a0 100644 --- a/requirements/static/ci/py3.11/darwin.txt +++ b/requirements/static/ci/py3.11/darwin.txt @@ -4,7 +4,7 @@ # # pip-compile --output-file=requirements/static/ci/py3.11/darwin.txt requirements/darwin.txt requirements/pytest.txt requirements/static/ci/common.in requirements/static/ci/darwin.in requirements/static/pkg/darwin.in # -aiohttp==3.8.4 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.3.1 # via aiohttp diff --git a/requirements/static/ci/py3.11/freebsd.txt b/requirements/static/ci/py3.11/freebsd.txt index 20e04b2a23b..3bc3a8c2e96 100644 --- a/requirements/static/ci/py3.11/freebsd.txt +++ b/requirements/static/ci/py3.11/freebsd.txt @@ -4,7 +4,7 @@ # # pip-compile --no-emit-index-url --output-file=requirements/static/ci/py3.11/freebsd.txt requirements/base.txt requirements/pytest.txt requirements/static/ci/common.in requirements/static/ci/freebsd.in requirements/static/pkg/freebsd.in requirements/zeromq.txt # -aiohttp==3.8.4 +aiohttp==3.8.5 # via etcd3-py aiosignal==1.3.1 # via aiohttp diff --git a/requirements/static/ci/py3.11/linux.txt b/requirements/static/ci/py3.11/linux.txt index d9bd3aa189e..19be3c22072 100644 --- a/requirements/static/ci/py3.11/linux.txt +++ b/requirements/static/ci/py3.11/linux.txt @@ -6,7 +6,7 @@ # aiohttp-retry==2.8.3 # via twilio -aiohttp==3.8.4 +aiohttp==3.8.5 # via # aiohttp-retry # etcd3-py diff --git a/requirements/static/ci/py3.8/linux.txt b/requirements/static/ci/py3.8/linux.txt index 4290692470d..392df3942ab 100644 --- a/requirements/static/ci/py3.8/linux.txt +++ b/requirements/static/ci/py3.8/linux.txt @@ -11,7 +11,7 @@ aiohttp==3.8.5 # aiohttp-retry # etcd3-py # twilio -aiosignal==1.2.0 +aiosignal==1.3.1 # via aiohttp ansible-core==2.11.12 # via ansible diff --git a/requirements/static/ci/py3.9/linux.txt b/requirements/static/ci/py3.9/linux.txt index bba8b36f856..76b5486ab88 100644 --- a/requirements/static/ci/py3.9/linux.txt +++ b/requirements/static/ci/py3.9/linux.txt @@ -11,7 +11,7 @@ aiohttp==3.8.5 # aiohttp-retry # etcd3-py # twilio -aiosignal==1.2.0 +aiosignal==1.3.1 # via aiohttp ansible-core==2.15.0 # via ansible From 23e96fdc6d6a2d066b21e1a80ac17e00c458123c Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Fri, 21 Jul 2023 20:06:53 +0100 Subject: [PATCH 46/46] Run `pyupgrade` on the changes from the merge-forward Signed-off-by: Pedro Algarvio --- tests/pytests/functional/modules/test_service.py | 2 +- tests/pytests/functional/states/test_service.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/pytests/functional/modules/test_service.py b/tests/pytests/functional/modules/test_service.py index 51ce7f1cc0b..a54ff1fbe6c 100644 --- a/tests/pytests/functional/modules/test_service.py +++ b/tests/pytests/functional/modules/test_service.py @@ -36,7 +36,7 @@ def service_name(grains, modules): service_name = "Spooler" if os_family != "Windows" and salt.utils.path.which(cmd_name) is None: - pytest.skip("{} is not installed".format(cmd_name)) + pytest.skip(f"{cmd_name} is not installed") if is_systemd and modules.service.offline(): pytest.skip("systemd is OFFLINE") diff --git a/tests/pytests/functional/states/test_service.py b/tests/pytests/functional/states/test_service.py index a1e9673653b..fd023df0637 100644 --- a/tests/pytests/functional/states/test_service.py +++ b/tests/pytests/functional/states/test_service.py @@ -43,7 +43,7 @@ def service_name(grains, modules): service_name = "Spooler" if os_family != "Windows" and salt.utils.path.which(cmd_name) is None: - pytest.skip("{} is not installed".format(cmd_name)) + pytest.skip(f"{cmd_name} is not installed") if is_systemd and modules.service.offline(): pytest.skip("systemd is OFFLINE")