Skip to content

Commit

Permalink
Update salt-ssh state wrapper pillar handling
Browse files Browse the repository at this point in the history
Instead of passing the pre-rendered pillar as an override, do it like
the regular `state` execution module does with `salt-call`: Check if the
pillar needs to be rendered, otherwise reuse the already rendered one.

Also, ensure that __pillar__ in wrapper modules contains the same one
used during rendering, same thing for the one passed to `state.pkg`.

Also, ensure that when pillars are rerendered during a state run, they
get the master opts in addition to the minion ones, since some modules
used in the pillar can rely on them to be present.

Also, ensure pillar overrides are accepted for the same functions as with
the regular `state` execution module.
  • Loading branch information
lkubb committed Oct 30, 2023
1 parent 5d14582 commit ae2ae33
Show file tree
Hide file tree
Showing 6 changed files with 457 additions and 55 deletions.
1 change: 1 addition & 0 deletions changelog/59802.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed merging of complex pillar overrides with salt-ssh states
1 change: 1 addition & 0 deletions changelog/62230.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Made salt-ssh states not re-render pillars unnecessarily
1 change: 1 addition & 0 deletions changelog/65483.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Ensured the pillar in SSH wrapper modules is the same as the one used in template rendering when overrides are passed
44 changes: 40 additions & 4 deletions salt/client/ssh/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,17 @@ class SSHState(salt.state.State):
Create a State object which wraps the SSH functions for state operations
"""

def __init__(self, opts, pillar=None, wrapper=None, context=None):
def __init__(
self,
opts,
pillar_override=None,
wrapper=None,
context=None,
initial_pillar=None,
):
self.wrapper = wrapper
self.context = context
super().__init__(opts, pillar)
super().__init__(opts, pillar_override, initial_pillar=initial_pillar)

def load_modules(self, data=None, proxy=None):
"""
Expand All @@ -49,6 +56,21 @@ def load_modules(self, data=None, proxy=None):
)
self.rend = salt.loader.render(self.opts, self.functions)

def _gather_pillar(self):
"""
The opts used during pillar rendering should contain the master
opts in the root namespace. self.opts is the modified minion opts,
containing the original master opts in `__master_opts__`.
"""
_opts = self.opts
popts = {}
popts.update(_opts.get("__master_opts__", {}))
popts.update(_opts)
self.opts = popts
pillar = super()._gather_pillar()
self.opts = _opts
return pillar

def check_refresh(self, data, ret):
"""
Stub out check_refresh
Expand All @@ -69,10 +91,24 @@ class SSHHighState(salt.state.BaseHighState):

stack = []

def __init__(self, opts, pillar=None, wrapper=None, fsclient=None, context=None):
def __init__(
self,
opts,
pillar_override=None,
wrapper=None,
fsclient=None,
context=None,
initial_pillar=None,
):
self.client = fsclient
salt.state.BaseHighState.__init__(self, opts)
self.state = SSHState(opts, pillar, wrapper, context=context)
self.state = SSHState(
opts,
pillar_override,
wrapper,
context=context,
initial_pillar=initial_pillar,
)
self.matchers = salt.loader.matchers(self.opts)
self.tops = salt.loader.tops(self.opts)

Expand Down
Loading

0 comments on commit ae2ae33

Please sign in to comment.