您也可以参考在Github上维护的这一份技术资料:Requisites and Other Global State Arguments
Salt requisite 系统用于创建状态之间的关系。 核心思想是,当一种状态某种程度上依赖于另一种状态时,可以轻松定义相互依赖。 这些依赖性通过使用状态名称和ID或名称声明关系来表示。 必需目标的一般形式是
。 这种特定形式定义为 Requisite Reference 。
Requisite 分为两种类型:direct requisites(例如require
)和requisite_ins(例如require_in
)。 关系是有方向的:直接的先决条件需要其他状态的某些条件。 但是,Requisite_in将必需项插入指向目标状态的目标状态。 下面的示例演示了直接的必要条件:
vim:
pkg.installed
/etc/vimrc:
file.managed:
- source: salt://edit/vimrc
- require:
- pkg: vim
在上面的示例中,文件/etc/vimrc
的配置取决于vim软件包是否已安装。
requisite_in语句则相反。 Requisite_ins不会说“我依赖某事”,而是说“某人依赖我”:
vim:
pkg.installed:
- require_in:
- file: /etc/vimrc
/etc/vimrc:
file.managed:
- source: salt://edit/vimrc
因此,在这里,使用requisite_in可以完成与第一个示例相同的操作,但反之亦然。 vim软件包说“/etc/vimrc取决于我”。 这将导致将require
插入到针对vim
状态的/etc/vimrc
状态。
最后,将创建一个依赖关系图,并以有限且可预测的顺序执行所有操作。
Requisites 需要两条信息进行匹配:状态模块名称-例如 pkg
和标识符,例如 vim ,可以是ID(节的第一行)或-name
参数。
- require:
- pkg: vim
New in version 2016.3.0.
在版本2016.3.0中,状态模块名称被设置为可选。 如果省略状态模块,则将要求与ID匹配的所有状态,无论它们使用的是哪个模块。
- require:
- vim
为了了解如何匹配状态目标,了解状态编译器的工作方式将很有帮助。 考虑以下示例:
Deploy server package:
file.managed:
- name: /usr/local/share/myapp.tar.xz
- source: salt://myapp.tar.xz
Extract server package:
archive.extracted:
- name: /usr/local/share/myapp
- source: /usr/local/share/myapp.tar.xz
- archive_format: tar
- onchanges:
- file: Deploy server package
第一个公式将转换为字典,如下所示(以YAML表示,为简化起见,省略了一些属性)为高级数据:
Deploy server package:
file:
- managed
- name: /usr/local/share/myapp.tar.xz
- source: salt://myapp.tar.xz
公式中使用的file.managed
格式本质上是语法糖:最后,目标是file,在上面的Extract server package
状态中使用了file
。
ID声明和name
参数要求都匹配。 这意味着,在上面的“Deploy server package”示例中,require
requisite必须与Deploy server package
或/usr/local/share/myapp.tar.xz
匹配,因此以下两个版本的“ Extract server package”均可使用 :
# (Archive arguments omitted for simplicity)
# Match by ID declaration
Extract server package:
archive.extracted:
- onchanges:
- file: Deploy server package
# Match by name parameter
Extract server package:
archive.extracted:
- onchanges:
- file: /usr/local/share/myapp.tar.xz
name of requisite | state is only executed if target execution result is | state is only executed if target has changes | order 1.target 2.state (default) | comment or description |
---|---|---|---|---|
require | success | default | state will always execute unless target fails | |
watch | success | default | like require, but adds additional behaviour (mod_watch) | |
prereq | success | has changes (run individually as dry-run) | switched | like onchanges, except order |
onchanges | success | has changes | default | execute state if target execution result is success and target has changes |
onfail | failed | default | Only requisite where state exec. if target fails |
在这个表格中使用了以下简写形式:
state (= dependent state): state containing requisite
target (= state target) : state referenced by requisite
下面列表是可以在 Salt 中使用的直接必要性条件:
每一个直接必要性条件都有一个相应的 requisite_in条件:
其中有几个必要条件还支持使用 requisite_any 形式的声明:
所有必要条件都定义了特定的关系,并且始终与上面定义的依赖关系逻辑一起工作。
使用require
要求必需状态在从属状态之前执行。 包含需求条件的状态定义为从属状态。 require
语句中指定的状态定义为必需状态。 如果所需状态的执行成功,则从属状态将执行。 如果所需状态的执行失败,则从属状态将不会执行。 在上面的第一个示例中,文件/etc/vimrc
仅在成功安装vim软件包后才执行。
从Salt 0.16.0开始,可以依赖于一个完整的sls文件。 为此,首先要include sls文件,然后将状态设置为要求依赖于包含的sls文件:
include:
- foo
bar:
pkg.installed:
- require:
- sls: foo
这将添加在给定的sls文件中找到的所有状态声明。 这意味着将需要依赖于sls foo中的每个状态。 这使得在任何必要性定义的语句中轻松批处理大批状态非常容易。
New in version 2018.3.0.
使用require_any
要求至少有必需状态之一在从属状态之前执行。 包含require_any
必要条件的状态定义为从属状态。 require_any
语句中指定的状态定义为必需状态。 如果所需状态的执行至少有一个成功了,则将执行从属状态。 如果所有必需状态的执行均失败,则从属状态将不会执行。
A:
cmd.run:
- name: echo A
- require_any:
- cmd: B
- cmd: C
- cmd: D
B:
cmd.run:
- name: echo B
C:
cmd.run:
- name: /bin/false
D:
cmd.run:
- name: echo D
在此示例中,A将运行,因为指定的需求B,C或D中的至少一个将成功。
当其他状态发生变化时,watch
语句用于添加由以上状态变化可以引发的其他行为。
注意:如果一个状态仅在另一个状态发生更改时才执行,否则什么也不做,则应使用新的
onchanges
要求而不是watch
。watch
旨在在发生更改时添加其他行为,否则状态将正常执行。
包含watch
条件的状态被定义为watch状态
。 watch语句
中指定的状态被定义为watched状态
。 当watch状态
执行时,它将返回一个包含名为“ changes
”的键的字典。 下面是状态返回字典的两个示例,为清楚起见,显示在json中:
{
"local": {
"file_|-/tmp/foo_|-/tmp/foo_|-directory": {
"comment": "Directory /tmp/foo updated",
"__run_num__": 0,
"changes": {
"user": "bar"
},
"name": "/tmp/foo",
"result": true
}
}
}
{
"local": {
"pkgrepo_|-salt-minion_|-salt-minion_|-managed": {
"comment": "Package repo 'salt-minion' already configured",
"__run_num__": 0,
"changes": {},
"name": "salt-minion",
"result": true
}
}
}
如果watch
状态的“result
”为True
,则watch状态将正常执行;如果为False
,则watch状态将永远不会运行。watch
语句的此部分是复制了require
组件的功能。
如果watch
状态的“result
”为True
,并且“changes
”键包含填充的词典(更改在watched状态下发生),则watch requisite
可以添加其他行为。此附加行为由watch状态
模块中的mod_watch
函数定义。如果在watch状态
模块中存在mod_watch
函数,则除了正常watch状态
外还将调用该函数。在这种情况下,从mod_watch
函数返回的数据将被返回给master服务器,而从主监视功能返回的数据将被丢弃。
如果“ changes
”键包含一个空字典,则watch
条件的行为与require
必需的行为完全相同(watch状态
将在“result
”为True
时执行,而在“result
”为False
时失败)。
注意:并非所有状态模块都包含
mod_watch
。如果watch状态
模块中缺少mod_watch
,则watch条件
的行为与require条件
的行为完全相同。
使用watch
的一个很好的例子是service.running
状态。当service
监视一个状态时,除了Salt确保服务正在运行之外,还会在监视状态更改时重新加载/重新启动服务。
ntpd:
service.running:
- watch:
- file: /etc/ntp.conf
file.managed:
- name: /etc/ntp.conf
- source: salt://ntp/files/ntp.conf
New in version 2018.3.0.
包含watch_any
必要条件的状态被定义为监视状态。 watch_any
语句中指定的状态被定义为watched状态
。当受监视的状态执行时,它们将返回包含名为“changes
”的键的字典。
如果任何被监视状态的“result
”为True
,则监视状态将正常执行,如果所有状态均为False
,则监视状态将永远不会运行。watch的此部分复制了require
组件的功能。
如果任何被监视状态的“result
”为True
,并且“changes
”键包含填充了数据的词典(在watched状态下发生了更改),则watch requisite
条件可以添加其他行为。此附加行为由watch状态
模块中的mod_watch
函数定义。如果在监视状态模块中存在mod_watch
函数,则除了正常监视状态外还将调用该函数。在这种情况下,从mod_watch
函数返回的数据将被返回给master服务器,而主监视功能的返回数据将被丢弃。
如果“changes
”键包含一个空字典,则watch条件
的行为与require
必需的行为完全相同(watch状态
将在“result
”为True
时执行,而在“result
”为False
时失败)。
apache2:
service.running:
- watch_any:
- file: /etc/apache2/sites-available/site1.conf
- file: apache2-site2
file.managed:
- name: /etc/apache2/sites-available/site1.conf
- source: salt://apache2/files/site1.conf
apache2-site2:
file.managed:
- name: /etc/apache2/sites-available/site2.conf
- source: salt://apache2/files/site2.conf
在此示例中,如果两个file.managed
状态之一的结果为True
且已更改,则将重新加载/重新启动服务。
New in version 0.16.0.
prereq
允许根据尚未执行的状态的预期结果采取措施。包含prereq
条件的状态被定义为pre-requiring状态
。 prereq
语句中指定的状态则被定义为pre-required
状态。
评估prereq
条件后,pre-required状态
会报告是否需要任何更改。通过启用test = True
,将pre-required
的单个状态作为测试运行来完成。该测试运行将返回一个包含名为“changes
”的键的字典。 (有关“changes
”词典的示例,请参见上面的watch
部分。)
如果“changes
”键包含一个已填充数据的字典,则意味着pre-required
的状态期望在实际执行该状态时发生更改。pre-requiring
状态现在将实际运行。如果pre-requiring
状态成功执行,则将继续执行pre-required
状态。如果pre-requiring
状态失败,则将不会执行pre-required
状态。
如果“changes
”键包含一个空的词典,则意味着pre-required
状态将不会发生更改。此时,既不会执行pre-requiring
状态,也不会运行pre-required
状态。
在以下实际示例中显示了定义prereq
的最佳方式:当由于底层代码将要更改而应关闭服务时,在进行更新时该服务应脱机。在此示例中,graceful-down
是pre-requiring
的状态,而site-code
是pre-required
的状态。
graceful-down:
cmd.run:
- name: service apache graceful
- prereq:
- file: site-code
site-code:
file.recurse:
- name: /opt/site_code
- source: salt://site/code
在这种情况下,仅当site-code
状态希望通过file.recurse
调用部署新代码时,才会关闭apache服务器。 只有正常运行正常完成后,才会执行site-code
部署。
New in version 2014.7.0.
onfail
必要条件允许严格响应于另一个状态的失败而发生反应。 这可以通过多种方式使用,例如由于失败而执行第二次尝试来设置服务或开始执行单独的状态线程。
onfail
要求的应用方式与watch
的要求相同:
primary_mount:
mount.mounted:
- name: /mnt/share
- device: 10.0.0.45:/share
- fstype: nfs
backup_mount:
mount.mounted:
- name: /mnt/share
- device: 192.168.40.34:/share
- fstype: nfs
- onfail:
- mount: primary_mount
注意:将
failhard
(全局或在某个故障状态中)设置为True
将导致忽略onfail
,onfail_in
和onfail_any
需求。 如果要将设置为True
的全局failhard
与onfail
,onfail_in
或onfail_any
组合在一起,则必须在可能发生失败的状态下将failhard
显式设置为False
(覆盖全局设置)。
注意:从Salt的2016.11.0版本开始,
onfail
对多个列出的onfail
要求使用OR
逻辑。 在2016.11.0发行版之前,onfail
使用AND
逻辑。 有关更多信息,请参见问题#22370。
New in version 2018.3.0.
onfail_any
必要条件允许严格响应作为对至少一个其他状态失败的响应而发生。 这可以通过多种方式使用,例如由于失败而执行第二次尝试来设置服务或开始执行单独的状态线程。
onfail_any
必要条件的使用方式与require_any
和watch_any
相同:
primary_mount:
mount.mounted:
- name: /mnt/share
- device: 10.0.0.45:/share
- fstype: nfs
secondary_mount:
mount.mounted:
- name: /mnt/code
- device: 10.0.0.45:/code
- fstype: nfs
backup_mount:
mount.mounted:
- name: /mnt/share
- device: 192.168.40.34:/share
- fstype: nfs
- onfail_any:
- mount: primary_mount
- mount: secondary_mount
在此示例中,如果primary_mount
或secondary_mount
状态中的任何一个导致失败,则将装载backup_mount
。
New in version 2014.7.0.
onchanges
必要条件使状态仅在必需状态发生更改并且watched状态
的“result
”为True
时才适用。 这可能是更改系统后执行一个post hook
操作的有用方法。
如果一个状态具有多个onchanges
要求,则如果任何watched状态
发生变化,则该状态将触发。
注意:一个容易犯的错误是在应该使用
onchanges
时使用onchanges_in
。 例如,以下配置不正确:
myservice:
pkg.installed:
- name: myservice
file.managed:
- name: /etc/myservice/myservice.conf
- source: salt://myservice/files/myservice.conf
- mode: 600
cmd.run:
- name: /usr/libexec/myservice/post-changes-hook.sh
- onchanges_in:
- file: /etc/myservice/myservice.conf
这将建立一个必要性依赖的关系,其中cmd.run
状态始终执行,而file.managed
状态仅在cmd.run
状态发生更改时才执行(因为cmd.run
状态将命令结果包括为 变化)。
从语义上看,cmd.run
状态应该仅在文件状态发生更改时才运行,但请记住,必需关系涉及一个状态监视另一个状态,而Required_in
则相反:它强制指定状态监视使用了Required_in
声明的状态 。
正确的用法是:
myservice:
pkg.installed:
- name: myservice
file.managed:
- name: /etc/myservice/myservice.conf
- source: salt://myservice/files/myservice.conf
- mode: 600
cmd.run:
- name: /usr/libexec/myservice/post-changes-hook.sh
- onchanges:
- file: /etc/myservice/myservice.conf
New in version 2018.3.0.
onchanges_any
必需条件使一个状态仅应用其中一个必需的状态就能生成更改,如果watched状态
之一的“结果”为True。 这可能是更改系统方面后执行post hook
的一个有用方法。
myservice:
pkg.installed:
- name: myservice
- name: yourservice
file.managed:
- name: /etc/myservice/myservice.conf
- source: salt://myservice/files/myservice.conf
- mode: 600
file.managed:
- name: /etc/yourservice/yourservice.conf
- source: salt://yourservice/files/yourservice.conf
- mode: 600
cmd.run:
- name: /usr/libexec/myservice/post-changes-hook.sh
- onchanges_any:
- file: /etc/myservice/myservice.conf
- file: /etc/your_service/yourservice.conf
在此示例中,仅当file.managed
状态中的任何一个生成更改并且至少一个受监视状态的“result
”为True
时,才运行cmd.run
。
use
必要条件用于继承另一个id声明中传递的参数。 当许多文件需要具有相同的默认值时,这很有用。
/etc/foo.conf:
file.managed:
- source: salt://foo.conf
- template: jinja
- mkdirs: True
- user: apache
- group: apache
- mode: 755
/etc/bar.conf:
file.managed:
- source: salt://bar.conf
- use:
- file: /etc/foo.conf
该use
声明主要是针对networking状态而开发的,但可以在Salt的任何状态中使用。 这对于networking状态很有意义,因为它可以定义一长列选项,这些选项需要应用于多个网络接口。
use
语句不继承目标状态的必要性条件参数。 这也意味着一系列use
条件不会继承"继承的选项"。
New in version 2017.7.0.
runas
全局选项用于设置用户,该用户将用于在cmd.run
模块中运行命令。
django:
pip.installed:
- name: django >= 1.6, <= 1.7
- runas: daniel
- require:
- pkg: python-pip
在上述状态下,由cmd.run
运行的pip命令将由daniel
用户运行。
New in version 2017.7.2.
runas_password
全局选项用于设置runas
全局选项使用的密码。 指定runas
时,Windows上的cmd.run
要求使用此命令。 在状态中定义runas_password
时将设置它。
run_script:
cmd.run:
- name: Powershell -NonInteractive -ExecutionPolicy Bypass -File C:\\Temp\\script.ps1
- runas: frank
- runas_password: supersecret
在上述状态下,由cmd.run
运行的Powershell脚本将由frank用户使用supersecret
密码运行。
_in
versions of requisites所有的requisites
组件还具有相应的Requires_in
版本,其版本与常规副本相反。 下面的所有示例均以require_in
为例,但请注意,所有_in
requisites条件的工作方式均相同:它们在目标状态下产生正常的必备条件,该目标状态以定义了Required_in
的状态为目标。 因此,require_in
导致target状态会依赖于targeting状态。 类似地,watch_in
使target状态监视targeting状态。
如果一个状态声明需要被另一个状态声明所依赖,则require_in
可以实现这一点。 因此,这两个sls文件最后将是相同的:
Using require
httpd:
pkg.installed: []
service.running:
- require:
- pkg: httpd
Using require_in
httpd:
pkg.installed:
- require_in:
- service: httpd
service.running: []
在单独的sls文件中分配require时,require_in
语句特别有用。 例如,httpd可能需要用于设置PHP或mod_python的组件,这很常见,但是HTTP状态不需要在设置时就知道需要它的其他组件:
http.sls
httpd:
pkg.installed: []
service.running:
- require:
- pkg: httpd
php.sls
include:
- http
php:
pkg.installed:
- require_in:
- service: httpd
mod_python.sls
include:
- http
mod_python:
pkg.installed:
- require_in:
- service: httpd
现在,只有首先验证php
和mod_python
都已安装,才能启动httpd
服务器。 因此,这将允许在“事后”定义一个条件。