在Ansible中构建复杂字符串的正确方法

时间:2019-05-21 07:55:58

标签: azure ansible

在ansible中构建复杂字符串的正确方法是什么?

给出命令模块中az cli的示例:

---
- name: >
    LISTDELETED {{ DATABASE_LISTDELETED_DATABASE }} databases
    FROM {{ DATABASE_LISTDELETED_SQLSERVER }} sqlserver
  command: >
    az sql db list-deleted
    --resource-group "{{ DATABASE_LISTDELETED_RESOURCEGROUP }}"
    --server "{{ DATABASE_LISTDELETED_SQLSERVER }}"
    --query "{{ DATABASE_LISTDELETED_QUERY | default('[*]') }}"
    --output json
  register: DATABASE_LISTDELETED_RESULT
  • 例如,如果缺少查询,则需要处理缺少的参数,请省略--query参数。
  • 我想提前构建字符串,以便可以轻松调试构建的结果。
  • 首选解决方案在同一任务中,而且易于阅读。

编辑:基于@Zeitounator gist,我结束了。

---
- name: >
    LISTDELETED {{ DATABASE_LISTDELETED_DATABASE }} databases
    FROM {{ DATABASE_LISTDELETED_SQLSERVER }} sqlserver
  vars:
    listdelted_command: >
      az sql db list-deleted
      --resource-group "{{ DATABASE_LISTDELETED_RESOURCEGROUP }}"
      --server "{{ DATABASE_LISTDELETED_SQLSERVER }}"
      {% if DATABASE_LISTDELETED_QUERY is defined %}
      --query "{{ DATABASE_LISTDELETED_QUERY }}"
      {% endif %}
  command: "{{ listdelted_command }}"
  register: DATABASE_LISTDELETED_RESULT

2 个答案:

答案 0 :(得分:2)

需求2和需求3是互斥的:您可以在任务中提前构建var(例如,在执行ansible模块之前),但仅可用于该任务(请参见救援任务中的插图)。下面的示例)。

使用

default过滤器时,您可以处理特定未设置变量的默认值。如果要省略更复杂的字符串,则必须使用相关测试将其用if jinja2表达式包围。

这是我会在您的情况下尝试的方法(由于未安装az,因此没有可运行的数据库/查询,因此未经过全面测试)

- name: Store my command in a var
  set_fact:
    my_command: >-
      az sql db list-deleted
      --resource-group "{{ DATABASE_LISTDELETED_RESOURCEGROUP }}"
      --server "{{ DATABASE_LISTDELETED_SQLSERVER }}"
      {% if DATABASE_LISTDELETED_QUERY is defined %}
      --query "{{ DATABASE_LISTDELETED_QUERY }}"
      {% if %}
      --output json

- block:
    - name: >
        LISTDELETED {{ DATABASE_LISTDELETED_DATABASE }} databases
        FROM {{ DATABASE_LISTDELETED_SQLSERVER }} sqlserver
      command: "{{ my_command }}"
      register: DATABASE_LISTDELETED_RESULT
  rescue:
    - name: debug failed az command
      var:
        msg: |
          There as been an error running the following command:
          {{ my_command }}
          The reported error was:
          {{ DATABASE_LISTDELETED_RESULT.stderr }}
      debug:
        msg: "{{ msg.split('\n') }}"

注意:

  • set_fact会将提到的变量存储为当前主机的事实。然后,您可以在其他任务中为同一主机重用此变量。
  • 我使用了blockrescue来说明条件调试。修改以适应您的需求。
  • 在yaml折叠块上的-符号是strip chomping indicator,以确保为提高可读性而引入的代码中的新行不会干扰构造的命令。
  • msg.split('\n')只是将多行消息字符串转换为列表,以便于屏幕阅读。
  • 如果您的变量DATABASE_LISTDELETED_QUERY可以设置为空字符串,并且您还想处理这种情况以跳过--query参数,则可以将测试更改为DATABASE_LISTDELETED_QUERY | default() | length > 0

答案 1 :(得分:0)

您可以为此编写Jinja2模板,在其中可以使用if-else来包含命令的某些部分,例如--query

---
- name: >
    LISTDELETED {{ DATABASE_LISTDELETED_DATABASE }} databases
    FROM {{ DATABASE_LISTDELETED_SQLSERVER }} sqlserver
  command: >
    az sql db list-deleted
    --resource-group "{{ DATABASE_LISTDELETED_RESOURCEGROUP }}"
    --server "{{ DATABASE_LISTDELETED_SQLSERVER }}"
{% if DATABASE_LISTDELETED_QUERY %}
    --query "{{ DATABASE_LISTDELETED_QUERY | default('[*]') }}"
{% endif %}
    --output json
  register: DATABASE_LISTDELETED_RESULT

然后使用ansible模板模块对其进行解析

- name: Template a file to my-command.yml
  template:
    src: /mytemplates/foo.j2
    dest: /commands/my-command.yml