saltstack / saltstack/salt

[Bug]: deltaproxy ignores proxy_merge_pillar_in_opts, and drops a proxymodule module_executors declaration for sub-proxies

Open
#70,223 0 comments 0 reactions 0 assignees View on GitHub

@ggiesen is already working on this.

Since Sep 2, 2026.

Dominant language
Python
Stars
15.7k
Forks
5.6k
Avg merge
2d 44m
Merged PRs (30d)
80

Description

Description

Two places where deltaproxy's proxy setup diverges from the single-proxy metaproxy.

1. The control proxy's pillar is merged into opts unconditionally, ignoring proxy_merge_pillar_in_opts.

salt/metaproxy/proxy.py guards the merge:

if self.opts.get("proxy_merge_pillar_in_opts"):
    # Override proxy opts with pillar data when the user required. But do
    # not override master in opts.
    pillar = copy.deepcopy(self.opts["pillar"])
    ...
elif self.opts.get("proxy_mines_pillar"):

salt/metaproxy/deltaproxy.py has no guard -- it always merges, then evaluates proxy_mines_pillar as a separate if. So the documented option (default False) has no effect and the control proxy's pillar always overrides its opts.

This does not stop at the control proxy. Sub-proxy opts begin as a copy of the control proxy's opts (proxyopts = opts.copy() in subproxy_post_master_init), so anything the control proxy's pillar injected into opts is inherited by every sub-proxy.

2. A proxymodule's module_executors declaration is ignored for sub-proxies.

post_master_init reads it for the control proxy:

self.module_executors = self.proxy.get(
    f"{fq_proxyname}.module_executors", lambda: []
)()

subproxy_post_master_init never sets it, so when thread_return does getattr(minion_instance, "module_executors", []) the attribute is missing and it falls through to the opts default. The single-proxy metaproxy honours the declaration.

Setup

salt 3008.2, one control proxy dpcontrol with three sub-proxies using the dummy proxytype.

Steps to reproduce -- 1

Put a plain key in the control proxy's pillar and leave proxy_merge_pillar_in_opts unset:

# control proxy pillar
proxy:
  proxytype: deltaproxy
  ids: [minion1, minion2, minion3]
n_marker: LEAKED_FROM_PILLAR

Then read it back from opts only:

salt dpcontrol config.get n_marker omit_pillar=True
salt minion1   config.get n_marker omit_pillar=True
salt minion2   config.get n_marker omit_pillar=True

Observed: all three return LEAKED_FROM_PILLAR, so the pillar key became an opts key on the control proxy and on every sub-proxy.
Expected: empty, since proxy_merge_pillar_in_opts is not set. With it set to True the merge should happen, as it does for a single proxy.

Steps to reproduce -- 2

Give the proxymodule a module_executors function:

def module_executors():
    return ["direct_call"]

Instrumenting thread_return to report what it resolved shows the attribute is absent on every sub-proxy:

id=minion1 has_attr=False value='<MISSING>'
id=minion2 has_attr=False value='<MISSING>'
id=minion3 has_attr=False value='<MISSING>'

Expected: the sub-proxies pick up the proxymodule's declaration, as the control proxy and the single-proxy metaproxy do.

Versions Report
Salt Version:
           Salt: 3008.2
Python Version:
         Python: 3.10
Salt Package Information:
   Package Type: onedir

Both reproduce against the current 3008.x branch head.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Compare salt/metaproxy/deltaproxy.py with salt/metaproxy/proxy.py, starting at subproxy_post_master_init, post_master_init, and thread_return. Verify the relevant deltaproxy tests or reproduction setup, then confirm that proxy_merge_pillar_in_opts controls the merge and that sub-proxies honor the proxymodule's module_executors declaration.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devops, infrastructure
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.