我有一个在stdout_lines中看起来像这样的命令输出:
"stdout_lines": [
"Keystore type: jks",
"Keystore provider: SUN",
"",
"Your keystore contains 6 entries",
"",
"Alias name: alias1",
"Creation date: Oct 16, 2015",
"Entry type: PrivateKeyEntry",
"Certificate chain length: 1",
"Certificate[1]:",
"Owner: CN=*.example.com, O=Example, L=Some, ST=Where, C=DE",
"Issuer: CN=some issuer cert",
"Valid from: Wed Oct 14 02:00:00 CEST 2015 until: Thu Oct 18 14:00:00 CEST 2018",
"Signature algorithm name: SHA256withRSA",
"Subject Public Key Algorithm: 2048-bit RSA key",
"Version: 3",
"" ]
因此,从存储了多个证书的密钥库中,我喜欢将信息提取到字典列表中,如下所示:
"keystore_values": [
{"Alias name": "alias1", "Owner": "CN=*.example.com",
"Valid until": "Thu Oct 18 14:00:00 CEST 2018" },
{"Alias name": "alias2", "Owner": "CN=*.example2.com",
"Valid until": "Thu Oct 18 14:00:00 CEST 2018" },
{"Alias name": "alias3", "Owner": "CN=*.example3.com",
"Valid until": "Thu Oct 18 14:00:00 CEST 2018" }]
现在我觉得我应该用regex_findall来检查“stdout”,在那里我定义了我需要的所有部件然后我可以拉链它们
我对你的问题做了一些假设:
keytool -list -v
命令的输出,因为这就是它的样子。Ansible对于复杂的文本转换来说并不是一个很好的工具,这实际上就是你在这里所做的。我想建议两种不同的解决方案,都依靠某种外部工具来完成繁重的工作。
在这个例子中,我们使用awk
来读取keytool
的输出并生成JSON输出。
我已经将一些输出硬编码到这本剧本中进行测试;显然你会在实践中用command
任务替换它:
---
- hosts: localhost
gather_facts: false
vars:
storepass: secret
tasks:
- command: keytool -list -v -storepass {{ storepass }}
register: keytool
changed_when: false
- command:
args:
argv:
- "awk"
- "-F"
- ": "
- |
# this function prints out a single key as a JSON
# object
function print_key(key) {
if (not_first_key) print ","
not_first_key=1
print "{"
not_first_line=0
for (i in key) {
if (not_first_line) print ","
not_first_line=1
printf "\"%s\": \"%s\"\n", i, key[i]
}
print "}"
}
BEGIN {
split("", key)
print "["
}
# We recognize the start of a new key by the Alias name
# field. When we see it, we will (a) check if we have data
# for a prior key and print it out and then (b) reset the
# key array and start collecting new data.
/^Alias name/ {
if (length(key) > 0) {
print_key(key)
delete(key)
}
key["Alias name"] = $2
}
# The "Valid from" line requires special parsing.
/^Valid from/ {
key["Valid from"] = substr($2, 0, length($2)-6)
key["Valid until"] = $3
}
# Simple fields that we're interested in
/^(Owner|Issuer|Creation date)/ {
key[$1] = $2
}
END {
if (length(key) > 0) {
print_key(key)
}
print "]"
}
stdin: "{{ keytool.stdout }}"
register: keytool_json
changed_when: false
- set_fact:
key_list_1: "{{ keytool_json.stdout|from_json }}"
- debug:
var: key_list_1
运行上面的剧本将产生:
TASK [debug] **********************************************************************************
ok: [localhost] => {
"key_list_1": [
{
"Alias name": "alias1",
"Creation date": "Apr 25, 2019",
"Issuer": "CN=Alice McHacker, OU=Unknown, O=Example Company, Inc., L=Boston, ST=MA, C=US",
"Owner": "CN=Alice McHacker, OU=Unknown, O=Example Company, Inc., L=Boston, ST=MA, C=US",
"Valid from": "Thu Apr 25 19:14:01 EDT 2019",
"Valid until": "Wed Jul 24 19:14:01 EDT 2019"
},
{
"Alias name": "alias2",
"Creation date": "Apr 25, 2019",
"Issuer": "CN=Mallory Root, OU=Unknown, O=Example Company, Inc., L=New York, ST=NY, C=US",
"Owner": "CN=Mallory Root, OU=Unknown, O=Example Company, Inc., L=New York, ST=NY, C=US",
"Valid from": "Thu Apr 25 19:17:03 EDT 2019",
"Valid until": "Wed Jul 24 19:17:03 EDT 2019"
}
]
}
...我认为产生你想要的数据。
或者 - 可能更强大 - 您可以将逻辑移动到自定义过滤器插件中。如果我们在filter_plugins/keys_to_list.py
中添加以下内容:
#!/usr/bin/python
def filter_keys_to_list(v):
key_list = []
key = {}
for line in v.splitlines():
# Just skip lines that don't look like a Key: Value line.
if ': ' not in line:
continue
# Same logic as the awk script: "Alias name" identifies the
# start of key data.
if line.startswith('Alias name'):
if key:
key_list.append(key)
key = {}
field, value = line.split(': ', 1)
if field in ['Alias name', 'Owner', 'Issuer', 'Creation date']:
key[field] = value
elif field == 'Valid from':
key['Valid from'], key['Valid until'] = value.split(' until: ')
if key:
key_list.append(key)
return key_list
class FilterModule(object):
filter_map = {
'keys_to_list': filter_keys_to_list,
}
def filters(self):
return self.filter_map
然后我们的剧本变得更加简单:
---
- hosts: localhost
gather_facts: false
vars:
storepass: secret
tasks:
- command: keytool -list -v -storepass {{ storepass }}
register: keytool
changed_when: false
- set_fact:
key_list_2: "{{ keytool.stdout|keys_to_list }}"
- debug:
var: key_list_2
这产生了相同的最终输出:
TASK [debug] **********************************************************************************
ok: [localhost] => {
"key_list_2": [
{
"Alias name": "alias1",
"Creation date": "Apr 25, 2019",
"Issuer": "CN=Lars Kellogg-Stedman, OU=Unknown, O=The Odd Bit, L=Boston, ST=MA, C=US",
"Owner": "CN=Lars Kellogg-Stedman, OU=Unknown, O=The Odd Bit, L=Boston, ST=MA, C=US",
"Valid from": "Thu Apr 25 19:14:01 EDT 2019",
"Valid until": "Wed Jul 24 19:14:01 EDT 2019"
},
{
"Alias name": "alias2",
"Creation date": "Apr 25, 2019",
"Issuer": "CN=Mallory Root, OU=Unknown, O=The Odd Bit, L=New York, ST=NY, C=US",
"Owner": "CN=Mallory Root, OU=Unknown, O=The Odd Bit, L=New York, ST=NY, C=US",
"Valid from": "Thu Apr 25 19:17:03 EDT 2019",
"Valid until": "Wed Jul 24 19:17:03 EDT 2019"
}
]
}