Ansible 过滤器 return 可以未定义吗?
Can an Ansible filter return Undefined?
我正在编写一个 Ansible 过滤器。有没有可能这个filter returns Undefined
,所以结果输出是Undefined
?
我的目标是在以下情况下可以将过滤器与 default
或 select
结合使用:
my_variable: "{{ my_input | myfilter | default(something) }}"
或:
my_list: "{{ list_of_things | map('myfilter') | select | list }}"
例如:
- vars:
area: 9
side: "{{ area | my_sqrt | default(0) }}"
debug:
var: side
或:
- vars:
numbers: [16, 9, -4]
roots: "{{ numbers | map('my_sqrt') | select | list }}"
debug:
var: roots
其中 map('my_sqrt')
应该输出 [4, 3, Undefined]
而 select
应该把它变成 [4, 3]
.
我试图将 my_sqrt
定义为:
import math
from jinja2.runtime import Undefined
def my_sqrt(input):
if input < 0:
return Undefined
else:
return math.sqrt(input)
class FilterModule(object):
def filters(self):
return { 'my_sqrt': my_sqrt }
但是,当我执行上面的剧本时,似乎 return 字符串 <class 'jinja2.runtime.Undefined'>
.
一些进一步的测试证明了这一点:
('never' if 0) | default('the_default')
确实returns the_default
.
然而,-4 | my_sqrt | default('the_default')
可悲的是 return 字符串 "<class 'jinja2.runtime.Undefined'>"
。
我都尝试过 jinja2.runtime.Undefined
和 ansible.template.AnsibleUndefined
。
我主要想知道 Ansible/Jinja2 过滤器是否可以 return Undefined
.
如果那不可能,我很想听听其他方法。我实际上正在写的是一个过滤器,它接受一个对象和一个选项列表(可能的匹配),并将 return 最佳选项(最佳匹配)。如果没有好的选项,应该returnUndefined
,之后就看剧本怎么处理了。作为基本要求,它应该适用于 default
和 select
.
您可以将 filter
定义为 return None
而不是 Undefined
。然后,您可以将输出通过管道传输到 select
和 default
过滤器,但需要注意。
None
将被 default
过滤器解释为布尔值。因此,您必须将值 true
作为 default
过滤器的第二个参数传递,它才能按预期工作。
使用此代码试试:
过滤器定义:
#!/bin/bash
import math
import typing as t
V = t.TypeVar("V")
def my_sqrt(value: V) -> t.Union[V , None]:
if value < 0:
return None
else:
return math.sqrt(value)
class FilterModule(object):
def filters(self):
return {
'my_sqrt': my_sqrt
}
剧本示例:
- hosts: localhost
gather_facts: no
tasks:
- name: Test the my_sqrt filter
debug:
msg: "{{ item | my_sqrt | default(0, true) }}"
loop:
- 4
- -1
- name: Select
debug:
msg: "{{ [4, 3, -4] | map('my_sqrt') | select | list }}"
您会看到 tasks
都按预期工作:
PLAY [localhost] ***************************************************************
Friday 14 May 2021 09:27:41 -0300 (0:00:00.019) 0:00:00.019 ************
TASK [Test the my_sqrt filter] *************************************************
ok: [localhost] => (item=4) =>
msg: '2.0'
ok: [localhost] => (item=-1) =>
msg: '0'
Friday 14 May 2021 09:27:41 -0300 (0:00:00.042) 0:00:00.062 ************
TASK [Select] ******************************************************************
ok: [localhost] =>
msg:
- 2.0
- 1.7320508075688772
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Friday 14 May 2021 09:27:41 -0300 (0:00:00.044) 0:00:00.106 ************
===============================================================================
Select ------------------------------------------------------------------ 0.04s
Test the my_sqrt filter ------------------------------------------------- 0.04s
我正在编写一个 Ansible 过滤器。有没有可能这个filter returns Undefined
,所以结果输出是Undefined
?
我的目标是在以下情况下可以将过滤器与 default
或 select
结合使用:
my_variable: "{{ my_input | myfilter | default(something) }}"
或:
my_list: "{{ list_of_things | map('myfilter') | select | list }}"
例如:
- vars:
area: 9
side: "{{ area | my_sqrt | default(0) }}"
debug:
var: side
或:
- vars:
numbers: [16, 9, -4]
roots: "{{ numbers | map('my_sqrt') | select | list }}"
debug:
var: roots
其中 map('my_sqrt')
应该输出 [4, 3, Undefined]
而 select
应该把它变成 [4, 3]
.
我试图将 my_sqrt
定义为:
import math
from jinja2.runtime import Undefined
def my_sqrt(input):
if input < 0:
return Undefined
else:
return math.sqrt(input)
class FilterModule(object):
def filters(self):
return { 'my_sqrt': my_sqrt }
但是,当我执行上面的剧本时,似乎 return 字符串 <class 'jinja2.runtime.Undefined'>
.
一些进一步的测试证明了这一点:
('never' if 0) | default('the_default')
确实returns the_default
.
然而,-4 | my_sqrt | default('the_default')
可悲的是 return 字符串 "<class 'jinja2.runtime.Undefined'>"
。
我都尝试过 jinja2.runtime.Undefined
和 ansible.template.AnsibleUndefined
。
我主要想知道 Ansible/Jinja2 过滤器是否可以 return Undefined
.
如果那不可能,我很想听听其他方法。我实际上正在写的是一个过滤器,它接受一个对象和一个选项列表(可能的匹配),并将 return 最佳选项(最佳匹配)。如果没有好的选项,应该returnUndefined
,之后就看剧本怎么处理了。作为基本要求,它应该适用于 default
和 select
.
您可以将 filter
定义为 return None
而不是 Undefined
。然后,您可以将输出通过管道传输到 select
和 default
过滤器,但需要注意。
None
将被 default
过滤器解释为布尔值。因此,您必须将值 true
作为 default
过滤器的第二个参数传递,它才能按预期工作。
使用此代码试试:
过滤器定义:
#!/bin/bash
import math
import typing as t
V = t.TypeVar("V")
def my_sqrt(value: V) -> t.Union[V , None]:
if value < 0:
return None
else:
return math.sqrt(value)
class FilterModule(object):
def filters(self):
return {
'my_sqrt': my_sqrt
}
剧本示例:
- hosts: localhost
gather_facts: no
tasks:
- name: Test the my_sqrt filter
debug:
msg: "{{ item | my_sqrt | default(0, true) }}"
loop:
- 4
- -1
- name: Select
debug:
msg: "{{ [4, 3, -4] | map('my_sqrt') | select | list }}"
您会看到 tasks
都按预期工作:
PLAY [localhost] ***************************************************************
Friday 14 May 2021 09:27:41 -0300 (0:00:00.019) 0:00:00.019 ************
TASK [Test the my_sqrt filter] *************************************************
ok: [localhost] => (item=4) =>
msg: '2.0'
ok: [localhost] => (item=-1) =>
msg: '0'
Friday 14 May 2021 09:27:41 -0300 (0:00:00.042) 0:00:00.062 ************
TASK [Select] ******************************************************************
ok: [localhost] =>
msg:
- 2.0
- 1.7320508075688772
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Friday 14 May 2021 09:27:41 -0300 (0:00:00.044) 0:00:00.106 ************
===============================================================================
Select ------------------------------------------------------------------ 0.04s
Test the my_sqrt filter ------------------------------------------------- 0.04s