I'd like to target highstate runs by state. This way I could, say, restart all apaches at the same time and be sure that I haven't missed any.
Like this:
salt -S apache state.highstate
Explanation: I write my states for, say, apache, with one basic state that sets everything that I want the same for all apaches (like the LogFormat, the mimesettings, etc) and include: that basic state from every other apache that gets deployed, however different its usecase may be.
When one is then confronted with something like the Heartbleed OpenSSL bug one would like to upgrade/restart all those apaches in one go.
I could work around this with pillar values but that feels like a kludge to me.
So what part of the state are you targeting with "apache"? The state ID? Is it supposed to include globbing? If you could clarify exactly what you want your example above to target, that would be really helpful.
OK, so here's an example from my config tree that I've edited slightly for brevity so please don't expect all names to line up:
top.sls
:
...
'osm-1':
- machine.osm.apache
- ...
machine/osm/apache/init.sls
:
include:
- apache
extend:
/etc/apache2/sites:
file.recurse:
- source: salt://machine/osm/apache/sites
/etc/apache2/conf/listen.conf:
file.managed:
- source: salt://machine/osm/apache/listen.conf
...
apache/init.sls
:
apache-pkgs:
pkg.installed:
- pkgs:
- apache2
apache2:
service.running:
- watch:
- file: /etc/apache2/apache2.conf
- cmd: apache-configtest
/etc/apache2/apache2.conf:
file.managed:
- source: salt://apache/apache2.conf
- require:
- pkg: apache-pkgs
/etc/apache2/sites:
file.recurse:
- source: salt://apache/sites
- template: jinja
- file_mode: 444
/etc/apache2/conf/listen.conf:
file.managed:
- source: salt://apache/listen.conf
- template: jinja
- mode: 444
delete-apache-files:
file.absent:
- names:
- /etc/apache2/httpd.conf
- /etc/apache2/ports.conf
- /etc/apache2/sites-enabled
enable-apache-ssl.conf:
file.symlink:
- name: /etc/apache2/mods-enabled/ssl.conf
- target: /etc/apache2/mods-available/ssl.conf
...
[more stuff related to SSL, iterates over pillar dict]
etc, etc. You can see that I 'override', for example, /etc/apache2/sites
in the machine-specific conf but leave lots of other states unaffected, so this way of writing configs is very useful to provide a default config that needs only small tweaks to be useful on different machines.
I'm not up to speed with the salt terminology, my use of 'apache' is referring to a filename, or rather a directory (apache/init.sls), but I guess a state ID (apache-pkgs
, apache2
, delete-apache-files
) would work too.
I don't know how useful globbing would be, you'd need to be very careful with state naming.
So the targeting system is used for minion targeting, not for state targeting. In your example above, how would the master know which minions to target with the command?
Also, I may be missing something, but doesn't salt '*' state.sls apache
fit your use case?
I'm asking for a command-line option. Parallel to salt -N [group] state.highstate
, salt -L '[list-of-minions]' state.highstate
, salt -G [grain] state.highstate
, salt -I [pillar] state.highstate
, etc.
And it's not that I want to run a specific state (your second question), I want to be unlimited ([insert evil laugh here]). To be specific further, no, it does not fit my use case, because the command you suggest would run the apache state on all minions, installing apache on all minions. I'd like it the other way around; to run a command on all minions that already have apache (or nginx or hiawatha or gcc or tomcat or whatever) installed (via a salt state of course).
To answer your first question: I thought that all commands were always sent to all minions and that the minion decides whether the command is meant for it or not. So it would not be the master that decides, it would be the minion that checks its list of states, sees whether it has the state in that list, and decides based on that whether it needs to run the command or not.
I hope I'm making more sense now...
I think I'm following better, though I'm not sure if this is a feature that's reasonable given the way the state system is currently setup. I'll have to ping @thatch45 on it, see what he thinks.
I'm also looking for the same thing. We will often edit one or two states and want to get those changes deployed out -- in a large deployment it can be difficult to determine which machines will get a specific state (includes obscure this quite a bit). Doing a massive bulk salt '*' state.highstate
isn't reasonable (because that can be a bit scary and, more practically, would take an absurd amount of time).
To clarify this requests we'd like to be able to do a "reverse lookup" of sorts where we can target by saying "find every machine that this state would apply to during a high state" and use those machines as the target.
I think that put another way, what this is requires is a top file targeting
system that's external to the highstate system. So you could say something
like:
salt '*' -T state.sls my_state
(And/or other combination of matchers.) Essentially, this would just make
top-files first-class citizens in the matcher system instead of being used
behind the scenes by the state system.
I think this direction has a lot of potential.
On Tue, Nov 25, 2014 at 9:24 AM, Jeff Minard [email protected]
wrote:
I'm also looking for the same thing. We will often edit one or two states
and want to get those changes deployed out -- in a large deployment it can
be difficult to determine which machines will get a specific state
(includes obscure this quite a bit). Doing a massive bulk salt '*'
state.highstate isn't reasonable (because that can be a bit scary and,
for more practical time considerations).To clarify this requests we'd like to be able to do a "reverse lookup" of
sorts where we can target by saying "find every machine that this state
would apply to during a high state" and use those machines as the target.—
Reply to this email directly or view it on GitHub
https://github.com/saltstack/salt/issues/11868#issuecomment-64426867.
I really like this idea, but keep in mind that it would need to be a very heavy matcher, since we would still need to compile at least the highstate on ALL minions every time this is run. While I like the idea we will need ot document the fact that it is still very heavy, all minions would still need to refresh pillar just to do the match.
So I will approve this, but we need a warning that it is a HEAVY matcher and that it will take more time to execute and will be heavy on the master.
Yeah, I don't know the internals of salt perfectly, but I did realized that this isn't in right now because it would, as noted, require basically touching a psuedo-highstate across all machines just to figure out who would get a state. That said, considering the alternative is to actually run that highstate instead across all machines, it's not too bad a trade off.
Not to bikeshed too much, but it would be nice if this were just another matcher, so the syntax could be any of the following (For example):
$ salt -T my_state state.sls my_state
$ salt -T my_state state.sls other_state
$ salt -T my_state cmd.run 'bar'
$ salt -C 'T@my_state and foo-* and G@num_cpu:1' pillar.get baz
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
If this issue is closed prematurely, please leave a comment and we will gladly reopen the issue.
stale bot is stale... i don't get why approved feature requests get marked 'stale'. I'm still interested!
Thank you for updating this issue. It is no longer marked as stale.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
If this issue is closed prematurely, please leave a comment and we will gladly reopen the issue.
still interested...
Thank you for updating this issue. It is no longer marked as stale.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
If this issue is closed prematurely, please leave a comment and we will gladly reopen the issue.
very much interested
Thank you for updating this issue. It is no longer marked as stale.
ZD-5829.
Please add this.
The use case is very common (as said by jeff-minard-ck) https://github.com/saltstack/salt/issues/11868#issuecomment-64426867
I currently do this in a script. roughly:
mkdir -p ~/.show_tops
for i in $(salt-run manage.up | sed -e 's/- //')
do
# shellcheck disable=SC2094
(salt "$i" state.show_top | tail -n +4 | head -n -10 > "$i")
done
wait
egrep -wl " - $1\$" ~/.show_tops/*
It is very handy, but also HEAVY.
Please add this.
Thanks for the idea! show_top doesn't give me what I want, but state.show_lowstate would, given some judicious grepping. (The bugreport above came from some experimenting :)
root@machine:~# salt web-1 state.show_lowstate --out json | fgrep __sls__ | tr -d \, | sort | uniq | fgrep apache
"__sls__": "apache"
"__sls__": "machine.web.apache"
"__sls__": "php-apache"
Some tweaking needed, but at least its going somewhere.
I figured that jq
& salt.show_highstate
can do the following:
$ sudo salt --out=json '*' state.show_highstate > js
## Find targets by SLS ID
$ cat js | jq -r 'select(.[][].__sls__ == "smtp_relay") | keys[]' | sort -u
## Find targets by state ID
$ cat js | jq -r 'select(.[] | has("/etc/postfix/main.cf")) | keys[]' | sort -u
## Sort state IDs by their number of occurrence
$ cat js | jq -r 'map(.[] = "")[] | keys[]' | sort -n | uniq -c | sort -n
And json is easier to parse with salt.show_lowstate
since it's got __id__
there:
$ sudo salt --out=json '*' state.show_lowstate > lowstate.json
## Find targets by SLS ID
$ cat lowstate.json | jq -r 'select(.[][].__sls__ == "smtp_relay") | keys[]' | sort -u
## Find targets by state ID
$ cat lowstate.json | jq -r 'select(.[][].__id__ == "/etc/postfix/main.cf") | keys[]' | sort -u
## Sort state IDs by their number of occurrence
$ cat lowstate.json | jq -r '.[][].__id__' | sort -n | uniq -c | sort -n
## Print "hostname,sls_id,state_id"
$ cat lowstate.json | jq -r 'keys[] as $host | .[][] | [ $host, .__sls__, .__id__ ] | join(",")' # for `sudo salt --out=json '*' state.show_lowstate > js`
Most helpful comment
Not to bikeshed too much, but it would be nice if this were just another matcher, so the syntax could be any of the following (For example):