【问题标题】:ansible nested loop fileglob ansible dictionary with_nestedansible 嵌套循环 fileglob ansible 字典 with_nested
【发布时间】:2021-04-18 12:19:49
【问题描述】:

假设我有以下树:

foo/
├─ bar/
│  ├─ secret/
│  │  ├─ directory_1/
│  │  │  ├─ file1
│  │  │  ├─ file2
│  │  ├─ directory_2/
│  │  │  ├─ file3
│  │  │  ├─ file4

我不知道 directory_1directory_2 中的文件是什么以及它们有多少,我希望能够在其中循环并列出它们。

我有以下 ansible dict :

my_directory_list:
  var1: secret_dir
  file:
    - directory: directory_1
      secret_name: secret_1
    - directory: directory_2
      secret_name: secret_2

还有以下任务:

- name: "my task"
  shell: echo ' in my directory : {{item.0.directory}} i have {{item.1}} '
  with_nested:
    - "{{my_root_directory.file}}"
    - "{{ lookup('fileglob', '/foo/bar/secret/{{item.0.directory}}') }}"

和预期的输出:

in my directory directory_1 i have file1
in my directory directory_1 i have file2
in my directory directory_2 i have file3
in my directory directory_2 i have file4

但我不能让它工作,因为 ansible 列表是空的,我试过了:

- "{{ lookup('fileglob', '/foo/bar/secret/{{item.0.directory}}').split(',') }}"

但列表仍然是空的,我做错了什么?是否可以仅使用 ansible 来实现这种输出?没有神社/蟒蛇?

感谢您的帮助,

【问题讨论】:

    标签: loops dictionary ansible jinja2


    【解决方案1】:

    首先,您的剧本中有几个语法错误会阻止它运行

    引用错误

    如果您在 YAML 值中使用引号,则必须引用整个内容。所以当你写的时候:

    - name: "my task"
      shell: echo ' in my directory : {{item.0.directory}} i have {{item.1}} '
    

    shell: 键的那个值会导致错误:

    ERROR! We were unable to read either as JSON nor YAML, these are the errors we got from each:
    JSON: Expecting value: line 1 column 1 (char 0)
    
    Syntax Error while loading YAML.
      mapping values are not allowed in this context
    

    您需要将整个值放在引号中,如下所示:

    - name: "my task"
      shell: "echo ' in my directory : {{item.0.directory}} i have {{item.1}} '"
    

    我更喜欢使用 YAML 的块引用运算符之一,如下所示:

    - name: "my task"
      shell: >-
        echo ' in my directory : {{item.0.directory}} i have {{item.1}} '
    

    这样可以避免在需要时玩转义游戏 命令行中的双引号和单引号。

    变量替换错误

    您永远不会嵌套 Jinja 模板标记 ({{...}})。当你写:

    - "{{ lookup('fileglob', '/foo/bar/secret/{{item.0.directory}}') }}"
    

    您最终将文字字符串 /foo/bar/secret/{{item.0.directory}} 传递给 fileglob 查找。你需要这样写:

    - "{{ lookup('fileglob', '/foo/bar/secret/' ~ item.0.directory) }}"
    

    ~ 是 Jinja 字符串连接运算符。但这仍然 不会工作,因为...

    逻辑错误

    循环变量item 在参数中不可用 with_nested(因为循环还没有开始执行,当 参数被解释),所以即使你修正了语法,你也会 看到以下失败:

    TASK [my task] *******************************************************************************************************************************************************************************
    fatal: [localhost]: FAILED! => {"msg": "'item' is undefined"}
    

    我会通过将任务分成两个独立的来解决这个问题 任务:一是查找文件,二是操作数据 (或显示它)。比如:

    - hosts: localhost
      gather_facts: false
      vars:
        my_directory_list:
          var1: secret_dir
          file:
            - directory: directory_1
              secret_name: secret_1
            - directory: directory_2
              secret_name: secret_2
    
      tasks:
        - name: "find files"
          find:
            path: "foo/bar/secret/{{ item.directory }}"
          register: files
          loop: "{{ my_directory_list.file }}"
    
        - name: "display results"
          debug:
            msg: "In my directory {{ item.0.item.directory }} I have {{ item.1.path|basename }}"
          loop: "{{ files.results|subelements('files') }}"
          loop_control:
            label: "{{ item.1.path }}"
    

    在上面的剧本中,“查找文件”任务使用find 模块来 获取列出的每个目录中的文件列表 my_directory_list.files。我们将这个循环的结果注册到 变量files。请参阅the documentation on the use of register in a loop 以了解该变量的结构。

    在“显示结果”任务中,我们迭代第一个结果 使用subelements 过滤器循环。这有效地给了我们一个 (directory, file_path) 元组的扁平化列表,因此我们可以生成 您正在寻找的输出。

    使用示例文件结构,运行上述 playbook 会产生以下输出:

    
    PLAY [localhost] *****************************************************************************************************************************************************************************
    
    TASK [find files] ****************************************************************************************************************************************************************************
    ok: [localhost] => (item={'directory': 'directory_1', 'secret_name': 'secret_1'})
    ok: [localhost] => (item={'directory': 'directory_2', 'secret_name': 'secret_2'})
    
    TASK [display results] ***********************************************************************************************************************************************************************
    ok: [localhost] => (item=foo/bar/secret/directory_1/file2) => {
        "msg": "In my directory directory_1 I have file2"
    }
    ok: [localhost] => (item=foo/bar/secret/directory_1/file1) => {
        "msg": "In my directory directory_1 I have file1"
    }
    ok: [localhost] => (item=foo/bar/secret/directory_2/file4) => {
        "msg": "In my directory directory_2 I have file4"
    }
    ok: [localhost] => (item=foo/bar/secret/directory_2/file3) => {
        "msg": "In my directory directory_2 I have file3"
    }
    
    PLAY RECAP ***********************************************************************************************************************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
    

    【讨论】:

    • 感谢您的回答,我需要按文件夹对文件运行一些 kubectl 机密,但我想我明白了您的逻辑,是的,您对我想同样的逻辑问题是正确的。 . 检查并在我回家后再次验证
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-12
    相关资源
    最近更新 更多