Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/69901.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed `salt.utils.functools` `namespaced_function`/`alias_function` dropping keyword-only argument defaults in copied function
1 change: 1 addition & 0 deletions changelog/69906.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed handling of keyword-only parameters and positional-only parameters when calling module functions, most notably from the CLI, in state application and via the mine or `module.run`.
1 change: 1 addition & 0 deletions changelog/69919.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed `module.run` handling of positional arguments to parameters that have default values
8 changes: 4 additions & 4 deletions salt/auth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,17 +601,17 @@ def cli(self, eauth):
)
return ret

args = salt.utils.args.arg_lookup(self.auth[fstr])
for arg in args["args"]:
aspec = salt.utils.args.get_function_argspec(self.auth[fstr])
for arg in aspec.allreq:
if arg in self.opts:
ret[arg] = self.opts[arg]
elif arg.startswith("pass"):
ret[arg] = getpass.getpass(f"{arg}: ")
else:
ret[arg] = input(f"{arg}: ")
for kwarg, default in list(args["kwargs"].items()):
for kwarg, default in aspec.alldefaults.items():
if kwarg in self.opts:
ret["kwarg"] = self.opts[kwarg]
ret[kwarg] = self.opts[kwarg]
else:
ret[kwarg] = input(f"{kwarg} [{default}]: ")

Expand Down
4 changes: 2 additions & 2 deletions salt/fileserver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,8 +504,8 @@ def envs(self, back=None, sources=False):
fstr = f"{fsb}.envs"
kwargs = (
{"ignore_cache": True}
if "ignore_cache" in _argspec(self.servers[fstr]).args
and self.opts["__role"] == "minion"
if self.opts["__role"] == "minion"
and "ignore_cache" in _argspec(self.servers[fstr]).namedargs
else {}
)
if sources:
Expand Down
4 changes: 2 additions & 2 deletions salt/master.py
Original file line number Diff line number Diff line change
Expand Up @@ -2494,7 +2494,7 @@ def _prep_pub(self, minions, jid, clear_load, extra, missing):

# Check if 'minions' is included in returner's save_load arg_spec.
# This may be missing in custom returners, which we should warn about.
if "minions" not in arg_spec.args:
if "minions" not in arg_spec.namedargs:
log.critical(
"The specified returner used for the external job cache "
"'%s' does not have a 'minions' kwarg in the returner's "
Expand Down Expand Up @@ -2522,7 +2522,7 @@ def _prep_pub(self, minions, jid, clear_load, extra, missing):
# always write out to the master job caches
try:
fstr = "{}.save_load".format(self.opts["master_job_cache"])
self.mminion.returners[fstr](clear_load["jid"], clear_load, minions)
self.mminion.returners[fstr](clear_load["jid"], clear_load, minions=minions)
except KeyError:
log.critical(
"The specified returner used for the master job cache "
Expand Down
29 changes: 14 additions & 15 deletions salt/minion.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ def load_args_and_kwargs(func, args, data=None, ignore_invalid=False):
_args = []
_kwargs = {}
invalid_kwargs = []
named_args = argspec.namedargs

for arg in args:
if isinstance(arg, dict) and arg.get("__kwarg__", False) is True:
Expand All @@ -393,30 +394,28 @@ def load_args_and_kwargs(func, args, data=None, ignore_invalid=False):
# Skip __kwarg__ when checking kwargs
if key == "__kwarg__":
continue
if argspec.keywords or key in argspec.args:
# Function supports **kwargs or is a positional argument to
# the function.
if argspec.keywords or key in named_args:
# Function supports **kwargs or has a parameter with
# this name that can be passed a keyword argument.
_kwargs[key] = val
else:
# **kwargs not in argspec and parsed argument name not in
# list of positional arguments. This keyword argument is
# invalid.
# **kwargs not in argspec and parsed argument name not
# a parameter that can be passed a keyword argument.
# This keyword argument is invalid.
invalid_kwargs.append(f"{key}={val}")
continue

else:
string_kwarg = salt.utils.args.parse_input([arg], condition=False)[
1
] # pylint: disable=W0632
string_kwarg = salt.utils.args.parse_input([arg], condition=False)[1]
if string_kwarg:
if argspec.keywords or next(iter(string_kwarg.keys())) in argspec.args:
# Function supports **kwargs or is a positional argument to
# the function.
if argspec.keywords or next(iter(string_kwarg)) in named_args:
# Function supports **kwargs or has a parameter with
# this name that can be passed a keyword argument.
_kwargs.update(string_kwarg)
else:
# **kwargs not in argspec and parsed argument name not in
# list of positional arguments. This keyword argument is
# invalid.
# **kwargs not in argspec and parsed argument name not
# a parameter that can be passed a keyword argument.
# This keyword argument is invalid.
for key, val in string_kwarg.items():
invalid_kwargs.append(f"{key}={val}")
else:
Expand Down
4 changes: 2 additions & 2 deletions salt/modules/saltutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -2009,7 +2009,7 @@ def runner(

if name in rclient.functions:
aspec = salt.utils.args.get_function_argspec(rclient.functions[name])
if "saltenv" in aspec.args:
if "saltenv" in aspec.namedargs:
kwarg["saltenv"] = saltenv

if name in ["state.orchestrate", "state.orch", "state.sls"]:
Expand Down Expand Up @@ -2095,7 +2095,7 @@ def wheel(name, *args, **kwargs):
try:
if name in wheel_client.functions:
aspec = salt.utils.args.get_function_argspec(wheel_client.functions[name])
if "saltenv" in aspec.args:
if "saltenv" in aspec.namedargs:
valid_kwargs["saltenv"] = saltenv

if jid:
Expand Down
10 changes: 6 additions & 4 deletions salt/pillar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1147,10 +1147,12 @@ def _external_pillar_data(self, pillar, val, key):
Builds actual pillar data structure and updates the ``pillar`` variable
"""
ext = None
args = salt.utils.args.get_function_argspec(self.ext_pillars[key]).args
valid_kwargs = salt.utils.args.get_function_argspec(
self.ext_pillars[key]
).namedargs

if isinstance(val, dict):
if ("extra_minion_data" in args) and self.extra_minion_data:
if ("extra_minion_data" in valid_kwargs) and self.extra_minion_data:
ext = self.ext_pillars[key](
self.minion_id,
pillar,
Expand All @@ -1160,7 +1162,7 @@ def _external_pillar_data(self, pillar, val, key):
else:
ext = self.ext_pillars[key](self.minion_id, pillar, **val)
elif isinstance(val, list):
if ("extra_minion_data" in args) and self.extra_minion_data:
if ("extra_minion_data" in valid_kwargs) and self.extra_minion_data:
ext = self.ext_pillars[key](
self.minion_id,
pillar,
Expand All @@ -1170,7 +1172,7 @@ def _external_pillar_data(self, pillar, val, key):
else:
ext = self.ext_pillars[key](self.minion_id, pillar, *val)
else:
if ("extra_minion_data" in args) and self.extra_minion_data:
if ("extra_minion_data" in valid_kwargs) and self.extra_minion_data:
ext = self.ext_pillars[key](
self.minion_id,
pillar,
Expand Down
16 changes: 3 additions & 13 deletions salt/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -1498,19 +1498,9 @@ def verify_data(self, data):
else:
# First verify that the parameters are met
aspec = salt.utils.args.get_function_argspec(self.states[full])
arglen = 0
deflen = 0
if isinstance(aspec.args, list):
arglen = len(aspec.args)
if isinstance(aspec.defaults, tuple):
deflen = len(aspec.defaults)
for ind in range(arglen - deflen):
if aspec.args[ind] not in data:
errors.append(
"Missing parameter {} for state {}".format(
aspec.args[ind], full
)
)
for arg in aspec.allreq:
if arg not in data:
errors.append(f"Missing parameter {arg} for state {full}")
# If this chunk has a recursive require, then it will cause a
# recursive loop when executing, check for it
reqdec = ""
Expand Down
4 changes: 2 additions & 2 deletions salt/states/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ def _get_systemd_only(func, kwargs):

ret = {}
warnings = []
valid_args = _argspec(func).args
valid_kwargs = _argspec(func).namedargs
for systemd_arg in SYSTEMD_ONLY:
if systemd_arg in kwargs and systemd_arg in valid_args:
if systemd_arg in kwargs and systemd_arg in valid_kwargs:
if _get_systemd_only.HAS_SYSTEMD:
ret[systemd_arg] = kwargs[systemd_arg]
else:
Expand Down
Loading
Loading