HTTP MODULES
本教程演示如何使用Salt中提供的各种HTTP模块。 这些模块包装了Python tornado,urllib2和requests库,以与Salt工作流程更加一致的方式扩展它们。
THE SALT.UTILS.HTTP LIBRARY
该库构成了HTTP模块的核心。 由于它被设计为在minion上用作执行模块,除了作为master上的runner之外,它被抽象到这个多用途库中。 此库也可以由希望利用其扩展功能的第三方程序导入使用。
Execution、state和runner程序模块的核心功能均是从此库派生的,这里描述了它们之间的常见用法。 下面对每个模块分别做了介绍。
该库可以通过以下方式导入:
import salt.utils.http
CONFIGURING LIBRARIES
这个库可以使用Salt所需的tornado,随Python一起提供的urllib2,或者可以单独安装的requests。 默认情况下,将使用tornado。 要切换到urllib2,请设置以下变量:
backend: urllib2
要切换至requests, 则设置以下变量:
backend: requests
这可以在master或minion配置文件中设置,也可以作为选项直接传递给任何http.query()函数。
SALT.UTILS.HTTP.QUERY()
此函数形成一个基本查询,但有一些附加功能未添加tornado、urllib2和requests库的支持。 并非所有这些库中当前可用的功能都已添加,但可以在将来的迭代中添加。
HTTPS REQUEST METHODS
只需一个URL调用此函数即可执行基本的查询:
salt.utils.http.query('http://example.com')
默认情况下,查询将使用GET方法执行。 可以使用method参数覆盖该方法:
salt.utils.http.query('http://example.com/delete/url', 'DELETE')
使用POST方法(以及其他方法,如PUT)时,通常也会发送额外数据。 这些数据可以直接发送(必要时可以进行URL编码),也可以采用远程服务器所需的任何格式(XML,JSON,纯文本等)。
salt.utils.http.query(
'http://example.com/post/url',
method='POST',
data=json.dumps(mydict)
)
DATA FORMATTING AND TEMPLATING
请记住,数据必须预先格式化; 此功能不会为您格式化。 但是,存储在本地系统上的模板化文件可以与变量一起传递以填充它。
仅传递文件(未使用模板):
salt.utils.http.query(
'http://example.com/post/url',
method='POST',
data_file='/srv/salt/somefile.xml'
)
要传递包含jinja + yaml模板的文件(默认值):
salt.utils.http.query(
'http://example.com/post/url',
method='POST',
data_file='/srv/salt/somefile.jinja',
data_render=True,
template_dict={'key1': 'value1', 'key2': 'value2'}
)
要传递包含mako模板的文件:
salt.utils.http.query(
'http://example.com/post/url',
method='POST',
data_file='/srv/salt/somefile.mako',
data_render=True,
data_renderer='mako',
template_dict={'key1': 'value1', 'key2': 'value2'}
)
因为此函数使用Salt自己的渲染系统,所以可以使用任何Salt渲染器。 因为Salt的渲染器需要设置__opts__
,所以应传入opts
字典。如果不是,则将使用节点类型(master或minion)的默认__opts__
值。 由于此库主要供minions
使用,因此默认节点类型为minion
。 但是,如果需要,可以将其更改为master
。
salt.utils.http.query(
'http://example.com/post/url',
method='POST',
data_file='/srv/salt/somefile.jinja',
data_render=True,
template_dict={'key1': 'value1', 'key2': 'value2'},
opts=__opts__
)
salt.utils.http.query(
'http://example.com/post/url',
method='POST',
data_file='/srv/salt/somefile.jinja',
data_render=True,
template_dict={'key1': 'value1', 'key2': 'value2'},
node='master'
)
HEADERS
Headers 也可以传递,作为header_list
、header_dict
或header_file
。 与data_file
一样,header_file
也可以是模板化的。 请注意,因为HTTP Headers通常是语法正确的YAML,所以它们将自动导入为Python dict。
salt.utils.http.query(
'http://example.com/delete/url',
method='POST',
header_file='/srv/salt/headers.jinja',
header_render=True,
header_renderer='jinja',
template_dict={'key1': 'value1', 'key2': 'value2'}
)
因为Headers和数据之间模板化的大部分数据可能相同,所以template_dict
对于两者都是相同的。 纠正可能的变量名称冲突需要用户自行处理。
AUTHENTICATION
query()函数支持基本的HTTP身份验证。 用户名和密码可以分别作为username和password传递。
salt.utils.http.query(
'http://example.com',
username='larry',
password=`5700g3543v4r`,
)
COOKIES AND SESSIONS
使用Python的内置cookielib
也可以支持Cookies
。 但是,默认情况下它们处于关闭状态。 要打开Cookies,请将Cookies
设置为True。
salt.utils.http.query(
'http://example.com',
cookies=True
)
默认情况下,cookies存储在Salt的缓存目录中,通常是/var/cache/salt
,作为名为cookies.txt
的文件。 但是,可以使用cookie_jar
参数更改此位置:
salt.utils.http.query(
'http://example.com',
cookies=True,
cookie_jar='/path/to/cookie_jar.txt'
)
默认情况下,cookie jar的格式是LWP(aka,lib-www-perl)。 选择此默认值是因为它是人可读的文本文件。 如果需要,可以将cookie jar的格式设置为Mozilla:
salt.utils.http.query(
'http://example.com',
cookies=True,
cookie_jar='/path/to/cookie_jar.txt',
cookie_format='mozilla'
)
由于Salt命令通常是通过管道连接在一起的一次性命令,因此该库通常不能像普通浏览器那样运行,会话cookie在多个HTTP请求中持续存在。 但是,会话可以保存在单独的cookie jar中。 在Salt的缓存目录中,此文件的默认文件名是cookies.session.p
。 这也可以改变。
salt.utils.http.query(
'http://example.com',
persist_session=True,
session_cookie_jar='/path/to/jar.p'
)
这个文件的格式是msgpack,这与Salt内部结构的大部分内容一致。 传统上,此文件的扩展名为.p
。 目前没有计划使其可配置。
PROXY
如果使用tornado后端(tornado是默认值),将使用在__opts__
字典中的proxy_host
,proxy_port
,proxy_username
,proxy_password
和no_proxy
中配置的代理信息。 通常这些是在minion配置文件中设置的。
proxy_host: proxy.my-domain
proxy_port: 31337
proxy_username: charon
proxy_password: obolus
no_proxy: ['127.0.0.1', 'localhost']
salt.utils.http.query(
'http://example.com',
opts=__opts__,
backend='tornado'
)
RETURN DATA
注意:返回编码格式的数据
如果
decode
设置为True
,则query()
将尝试解码返回数据。decode_type
默认为auto
。 例如,将其设置为特定的编码xml
,以覆盖自动检测。
由于Salt的http库旨在与REST接口一起使用,因此当decode
设置为True
时,query()
将尝试解码从远程服务器接收的数据。 首先,它将检查Content-type
headers头以尝试查找对XML的引用。 如果找不到,它将查找对JSON的引用。 如果没有找到,它将回退到纯文本,不会被解码。
使用Python的内置json库
将JSON数据转换为dict。 XML是使用salt.utils.xml_util
翻译的,它将使用Python的内置XML库来尝试将XML转换为dict。 为了强制JSON或XML解码,可以设置decode_type
:
salt.utils.http.query(
'http://example.com',
decode_type='xml'
)
一旦执行了转换,query()的返回字典将包含一个名为dict
的字典。
如果不使用这些方法之一来转换数据,则可以关闭解码。
salt.utils.http.query(
'http://example.com',
decode=False
)
如果启用了解码,并且找不到对JSON或XML的引用,则此模块将默认为纯文本,并将未解码的数据作为text
返回(即使文本设置为False
;请参见下文)。
query()
函数可以根据需要返回HTTP状态代码、标题和/或文本。 但是,每个必须单独配置和启用。
salt.utils.http.query(
'http://example.com',
status=True,
headers=True,
text=True
)
从以上查询所得到的返回字典中可以找到status, headers 和 text。
WRITING RETURN DATA TO FILES
只要从服务器收到响应,就可以将返回数据或headers头写入文件,可以通过text_out
或headers_out
参数指定文件位置。 不需要将文本和headers返回给用户以执行此操作。
salt.utils.http.query(
'http://example.com',
text=False,
headers=False,
text_out='/path/to/url_download.txt',
headers_out='/path/to/headers_download.txt',
)
SSL VERIFICATION
默认情况下,此功能将验证SSL证书。 但是,出于测试或调试目的,可以关闭SSL验证。
salt.utils.http.query(
'https://example.com',
verify_ssl=False,
)
CA BUNDLES
Requests
库有自己的方法来检测要使用的CA(证书颁发机构)bundle文件。 通常,这是由证书打包程序为您正在使用的特定操作系统分发实现的。 但是,urllib2
需要更多的工作。 默认情况下,Salt将尝试自动检测此文件的位置。 但是,如果它不在预期的位置,或者需要指定不同的路径,则可以使用ca_bundle
变量来完成。
salt.utils.http.query(
'https://example.com',
ca_bundle='/path/to/ca_bundle.pem',
)
UPDATING CA BUNDLES
update_ca_bundle()
函数可用于更新指定位置的包文件。 如果未指定目标位置,则它将尝试自动检测bundle文件的位置。 如果从中下载bundle绑包的URL不存在,则将从cURL网站下载bundle包。
注意: 应始终指定target和source! 未能指定目标可能导致文件被写入本地系统上的错误位置。 未指定源可能导致上游URL接收过多的不必要流量,并且可能导致下载文件是危险的或不满足用户的需要。
salt.utils.http.update_ca_bundle(
target='/path/to/ca-bundle.crt',
source='https://example.com/path/to/ca-bundle.crt',
opts=__opts__,
)
还应始终指定opts
参数。 如果是,则target
和source
可以分别在相关配置文件(master或minion)中指定为ca_bundle
和ca_bundle_url
。
ca_bundle: /path/to/ca-bundle.crt
ca_bundle_url: https://example.com/path/to/ca-bundle.crt
如果Salt无法自动检测CA包的位置,则会引发错误。
update_ca_bundle()
函数也可以传递一个字符串或表示本地系统上文件的字符串列表,这些文件应该(以指定的顺序)附加到CA包文件的末尾。 这在需要提供私有证书的环境中非常有用,并且在添加到bundle文件时不合理。
salt.utils.http.update_ca_bundle(
opts=__opts__,
merge_files=[
'/etc/ssl/private_cert_1.pem',
'/etc/ssl/private_cert_2.pem',
'/etc/ssl/private_cert_3.pem',
]
)
TEST MODE
此功能可以在测试模式下运行。 此模式将执行所有工作,直到实际的HTTP请求。 默认情况下,不会执行请求,而是返回空的dict。 在启用TRACE
日志记录的情况下使用此功能将显示要发送的headers头和POST数据的内容。
建议改为传入一个备用的test_url
而不是返回空的dict。如果检测到这种情况,则测试模式将使用test_url
替换url
,在返回数据中将test
设置为True
,并照常执行其余的请求操作。 这允许在必要时使用自定义的非重要的URL进行测试。
EXECUTION MODULE
http执行模块
是salt.utils.http
库的一个非常简单的包装器。 opts
也可以传入,但如果未指定,则将根据需要使用minion默认值。
因为从命令行传递完整的数据结构面对风险上(在执行注入攻击方面)更加棘手,所以data_file
和header_file
可能会在这里看到更多用途。
该库的所有方法都可以在执行模块中找到,比如kwargs
。
salt myminion http.query http://example.com/restapi method=POST \
username='larry' password='5700g3543v4r' headers=True text=True \
status=True decode_type=xml data_render=True \
header_file=/tmp/headers.txt data_file=/tmp/data.txt \
header_render=True cookies=True persist_session=True
RUNNER MODULE
与执行模块一样,http runner
模块也是salt.utils.http库的一个简单的包装器。 唯一显著的区别是,因为运行程序在master上而不是minion上执行,所以不需要目标,并且默认opts
将从master配置而不是minion配置派生。
该库的所有方法都可以在runner模块中找到,比如kwargs
。
salt-run http.query http://example.com/restapi method=POST \
username='larry' password='5700g3543v4r' headers=True text=True \
status=True decode_type=xml data_render=True \
header_file=/tmp/headers.txt data_file=/tmp/data.txt \
header_render=True cookies=True persist_session=True
STATE MODULE
状态模块是 runner module 的包装器,它将状态逻辑应用于查询。 上面列出的所有kwargs都在状态文件中指定,但是还有两个kwargs可用于应用有状态逻辑。 一个必需参数是match
,它指定要在返回文本中查找的模式。 默认情况下,这将执行字符串比较,在返回文本中查找匹配值。 在Python术语中,这看起来像:
if match in html_text:
return True
如果需要更复杂的模式匹配,则可以通过指定match_type
来使用正则表达式。 默认情况下,它设置为string
,但可以手动将其设置为pcre
。 请注意,这将使用Python的re.search()
而不是re.match()
。
因此,以下状态是有效的:
http://example.com/restapi:
http.query:
- match: 'SUCCESS'
- username: 'larry'
- password: '5700g3543v4r'
- data_render: True
- header_file: /tmp/headers.txt
- data_file: /tmp/data.txt
- header_render: True
- cookies: True
- persist_session: True
http://example.com/restapi:
http.query:
- match_type: pcre
- match: '(?i)succe[ss|ed]'
- username: 'larry'
- password: '5700g3543v4r'
- data_render: True
- header_file: /tmp/headers.txt
- data_file: /tmp/data.txt
- header_render: True
- cookies: True
- persist_session: True
除了匹配模式之外,可以检查URL的状态代码。 这是使用status
参数完成的:
http://example.com/:
http.query:
- status: '200'
如果同时指定了两者,则将检查两者,但如果只有一个为True
而另一个为False
,则返回False
。 在这种情况下,返回数据中的注释将包含用于故障排除的信息。
因为这是一个监视状态,它会将额外的数据返回给期望它的代码。 此数据将始终包含text
和status
。 可选地,还可以通过将Headers和解码参数分别设置为True
来请求headers
和dict
字典。