使用不同的Ansible运算符
在本节中,我们将学习可与Ansible playbooks一起使用的不同运算符,以执行不同的任务。对于数学运算,我们可以使用算术运算符,同样对于比较,我们可以使用比较运算符和测试运算符等等。我们将详细讨论这些单独的操作符。
算术运算符
在本节中,我们将使用不同的算术运算符在ansible剧本中执行一些数学计算。我们将使用通用的算术运算符,我们将在Jinja2语法中的任何地方使用这些运算符作为变量。
算术运算符列表
表达式 | 定义 |
---|---|
+ | 将两个对象相加。通常对象是数字,但如果两者都是字符串或者列表,则可以通过这种方式连接它们。 |
- | 从第一个数中减去第二个数。{{3-2}} 是'1'。 |
/ | 除以两个数字。返回值将是一个浮点数。{{1/2}} 是{0.5}}。 |
// | 除以两个数字并返回截断的整数结果。{20//7}} 是'2'。 |
% | 计算整数除法的余数。{11%7}} 是'4'。 |
* | 将左操作数与右操作数相乘。{{2*2}} 将返回'4'。 |
** | 将左操作数提升到右操作数的幂。{{2**3}} 将返回'8'。 |
在这个示例剧本中arithmetic_operators.yml
我正在执行各种算术运算:
-- - name: Perform arithmetic operations hosts: localhost gather_facts: false vars: num1: 30 num2: 15 tasks: - name: "Calculations" debug: msg: - "The value of num1 is: {{ num1 }}" - "The value of num2 is: {{ num2 }}" - "Multiply num1 and num2: {{ num1*num2 }}" - "Add num1 and num2: {{ num1+num2 }}" - "Subtract num2 from num1: {{ num1-num2 }}" - "Divide num1 by num2: {{ num1/num2 }}" - "Check remainder: {{ num1%num2 }}"
让我们执行剧本:
[ansible@controller ~]$ ansible-playbook arithmetic_operators.yml PLAY [Perform arithmetic operations] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *** TASK [Calculations] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ok: [localhost] => { "msg": [ "The value of num1 is: 30", "The value of num2 is: 15", "Multiply num1 and num2: 450", "Add num1 and num2: 45", "Subtract num2 from num1: 15", "Divide num1 by num2: 2.0", "Check remaininder: 0" ] } PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***** localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
你可以看到,我们定义了两个数值变量,对它们进行了各种不同的数学运算,如加法、减法、乘法、除法等,再简单不过了。
比较运算符
许多地方都用比较的方式来形容Ansible。任务条件是比较。Jinja2控制结构经常使用比较。一些过滤器也使用比较。要掌握Ansible对Jinja2的用法,了解哪些比较是可用的是很重要的。
与大多数语言一样,Jinja2配备了我们所期望的标准比较表达式集,它将呈现布尔值true或者false。
Jinja2中的表达式如下:
表达式 | 定义 |
---|---|
== | 比较两个对象是否相等 |
!= | 比较两个对象的不等式 |
> | 如果左侧大于右侧,则为真 |
@@ | 如果左侧小于右侧,则为True |
>= | 如果左侧大于或者等于右侧,则为真 |
@@@= | 如果左侧小于或者等于右侧,则为True |
在本节中,我创建了一个示例剧本"comparison-playbook.yml中我将使用两个变量的比较运算符
-- - name: Comparison Operators for Ansible hosts: localhost gather_facts: false vars: num1: 10 num2: 20 tasks: - debug: msg: - "The value of num1 is {{ num1 }} and num2 {{ num2 }}" - "num1 is equal to num2: {{ num1==num2 }}" - "num1 is not equal to num2: {{ num1 != num2 }}" - "num1 greater than num2: {{ num1 > num2 }}" - "num1 is less than num2: {{ num1 < num2 }}" - "num1 is greater than or equal to num2: {{ num1 >= num2 }}" - "num1 is less than or equal to num2: {{ num1 >= num2 }}"
让我们检查这个剧本执行的输出:
[ansible@controller ~]$ ansible-playbook comparison-playbook.yml PLAY [Comparison Operators for Ansible] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** TASK [debug] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *** ok: [localhost] => { "msg": [ "The value of num1 is 10 and num2 20", "num1 is equal to num2: False", "num1 is not equal to num2: True", "num1 greater than num2: False", "num1 is less than num2: True", "num1 is greater than or equal to num2: False", "num1 is less than or equal to num2: False" ] } PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***** localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
从输出可以检查比较运算符结果的状态。根据比较检查,我们得到的返回值为"TRUE"或者"FALSE"
测试操作符
Jinja2中的一个测试用于查看值是否有意义。实际上,is操作符用于启动测试。测试用于任何需要布尔结果的地方,例如if表达式和任务条件。有许多内置测试,但我们将重点介绍一些特别有用的测试:
defined
:如果变量已定义,则返回trueundefined
:定义的反义词none
:如果定义了变量,但值为none,则返回trueeven
:如果数字可被2整除,则返回trueodd
:如果数字不能被2整除,则返回true要测试一个值是否不是某物,只需使用"is not"。
在此示例剧本中test_operators.yml
我使用不同的测试操作符验证不同的场景:
-- - name: Test operators hosts: localhost gather_facts: false vars: list1: [this, is, a, sample, text] val1: "this" val2: "THIS" my_file_path: '/home/ansible/test_operators.yml' my_dir_path: '/home/ansible' my_link_path: '/tmp/dummy' my_name: 'hynman Prasad' num1: 20 tasks: - name: Validate test operators debug: msg: - "List contains {{ list1 }}" - "val1 is in list1: {{ val1 in list1 }}" - "val2 is in list1: {{ val2 in list1 }}" - "val2 is not in list1: {{ val2 not in list1 }}" - "num1 is defined: {{ num1 is defined }}" - "num2 is defined: {{ num2 is defined }}" - "num2 is undefined: {{ num2 is undefined }}" - "My name is lower case: {{ my_name is lower }}" - "num1 is even: {{ num1 is even }}" - "num1 is odd: {{ num1 is odd }}" - "Does file exists: {{ my_file_path is exists }}" - "Does directory exists: {{ my_dir_path is exists }}" - "Is {{ my_file_path }} a file: {{ my_file_path is file }}" - "Is {{ my_dir_path }} a directory: {{ my_dir_path is directory }}" - "Is {{ my_link_path }} a symbolic link: {{ my_link_path is link }}"
我不认为我需要解释剧本,因为它应该很清楚。我们正在尝试用不同的测试操作符验证多个场景。每个测试都会根据比较结果返回"TRUE"或者"FALSE"。
让我们来执行这个剧本:
[ansible@controller ~]$ ansible-playbook test_operators.yml PLAY [Test operators] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ** TASK [Validate test operators] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***** ok: [localhost] => { "msg": [ "List contains ['this', 'is', 'a', 'sample', 'text']", "val1 is in list1: True", "val2 is in list1: False", "val2 is not in list1: True", "num1 is defined: True", "num2 is defined: False", "num2 is undefined: True", "My name is lower case: False", "num1 is even: True", "num1 is odd: False", "Does file exists: True", "Does directory exists: True", "Is /home/ansible/test_operators.yml is a file: True", "Is /home/ansible is directory: True", "Is /tmp/dummy is a symbolic link: True" ] } PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***** localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
逻辑运算符
任何编程语言中的控制结构都提供了一种根据条件定义执行程序的路径的方法。除了条件逻辑,控制结构还为我们提供了一种在不复制代码的情况下重复类似任务的方法。这通常分别称为条件逻辑和循环。Jinja为我们提供了一组操作符,允许我们循环或者有条件地执行代码。在本节中,我们将专门讨论条件逻辑,并学习如何在Jinja的上下文中利用它。
代码形式的条件逻辑可能类似于以下内容(Python代码):
# Python Conditional Logic Example x = 0 if x == 0: print “Hello X is 0” else: print “Hello X is NOT 0”
这个Python代码提供了一个条件逻辑的简单示例。它只是说如果x等于0,那么执行print语句告诉用户。在Jinja中,我们可以实现一组非常相似的逻辑运算符。上下文中唯一真正的区别是,在Jinja中,所有的控制结构和条件化都被包装在{%%}
标记中。
下面是Jinja中的类似实现
{% if condition %} execute_this {% elif condition2 %} execute_this {% else %} execute_this {% endif %}
如我们所见,Jinja实现还提供了可选的else-if语句。在实现条件逻辑时,这为我们提供了额外的功能。
在这个示例playbook中,我们使用if条件检查变量,如果找到,则使用逻辑运算符打印或者打印其他内容:
-- - name: Logical Operator hosts: server2 gather_facts: false vars: hello: true say_something: "{% if hello == true %} Hello Jinja {% else %} Goodbye Ansible {% endif %}" tasks: - debug: msg: - "{{ say_something }}"
让我们来执行这个剧本:
[ansible@controller ~]$ ansible-playbook conditional-operator.yml PLAY [Logical Operator] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ** TASK [debug] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***** ok: [server2] => { "msg": [ " Hello Jinja " ] } PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *** server2 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
同样,让我们在下一个剧本"logical-operator.yml"中检查"其他一些逻辑运算符 . 在这个剧本中,我们将测试运算符与逻辑"and"和"or"运算符组合在一起。
-- - name: Logical Operators hosts: localhost gather_facts: false vars: x: 10 y: 15 list: [10,20,30] tasks: - debug: msg: - "The value of x is {{ x }} and the value of y is {{ y }}" - "Our list contains: {{ list }}" - "x < y and x in list: {{ x < y and x in list }}" - "x > y and x in list: {{ x > y and x in list }}" - "x in p or y in list: {{ x in list or y in list }}"
让我们来执行这个剧本:
[ansible@controller ~]$ ansible-playbook logical-operator.yml PLAY [Logical Operators] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***** TASK [debug] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***** ok: [localhost] => { "msg": [ "The value of x is 10 and the value of y is 15", "Our list contains: [10, 20, 30]", "x < y and x in list: True", "x > y and x in list: False", "x in p or y in list: True" ] } PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *** localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
这里我们比较x和y变量的值,并使用'and'和'or'条件检查列表中是否存在相应的变量。