【问题标题】:ansible AttributeError: 'list' object has no attribute 'startswith'ansible AttributeError: 'list' 对象没有属性 'startswith'
【发布时间】:2017-12-20 20:08:51
【问题描述】:

我正在运行 ansible 并试图使这个任务工作,它失败并出现以下错误:

任务执行期间发生异常。看到完整的 回溯,使用 -vvv。错误是: AttributeError: 'list' object has 没有属性“startswith”致命:[test-1]:失败! => {"failed": true, "msg": "模块执行过程中出现意外失败。", "stdout": ""} msg: 模块执行期间意外失败。

代码是:

  - name: Register env Type
    shell: facter configured_setup
    register: setup

  - name: foo tasks
    shell: {{some_script}} -t -a {{hosts}} -i {{inventory_hostname}}
    register: test
    when: setup.stdout == "something"

  - name: fetch group_vars
    fetch:
      src:
       - { "{{ item }}", when: setup.stdout == "something" }
      dest: "{{group_vars}}"
      flat: yes
    with_items:
      - "{{ test.stdout_lines[0] }}"
      - "{{ test.stdout_lines[1] }}"

“fetch group_vars”是总是失败的任务,知道它是如何工作的吗? 我想要做的是添加更多源文件以从不同的集合中获取。 所以我想在“src:”下多写几行,说- { filename, when setup.stdout =="something else" }

完整的错误是:

任务执行期间发生异常。完整的追溯是: 回溯(最近一次通话最后): 运行中的文件“/usr/lib/python2.7/site-packages/ansible/executor/task_executor.py”,第 96 行 item_results = self._run_loop(items) _run_loop 中的文件“/usr/lib/python2.7/site-packages/ansible/executor/task_executor.py”,第 252 行 res = self._execute(变量=task_vars) _execute 中的文件“/usr/lib/python2.7/site-packages/ansible/executor/task_executor.py”,第 446 行 结果 = self._handler.run(task_vars=variables) 运行中的文件“/usr/lib/python2.7/site-packages/ansible/plugins/action/fetch.py​​”,第 62 行 源 = self._remote_expand_user(源) _remote_expand_user 中的文件“/usr/lib/python2.7/site-packages/ansible/plugins/action/init.py”,第 460 行 if not path.startswith('~'): # FIXME: Windows 路径可能以 "~ 而不是 ~ AttributeError: 'list' 对象没有属性 'startswith'

致命:[test-1]:失败! => {“失败”:真,“味精”: “模块执行期间发生意外失败。”,“stdout”:“”} msg: 模块执行过程中出现意外故障。

【问题讨论】:

  • 当您开始像以前一样进行试验时,请确保您的缩进保持一致。您的 YAML 使用两个位置进行映射,四个位置用于序列(测量到元素的开头),但您在 src 下添加的序列使用三个位置。 YAML 可以将其分开,但如果您不一致,则很难自己管理。

标签: ansible ansible-2.x


【解决方案1】:

获取的 ansible documentation clearly states 获取文件,而不是文件列表。尽管可以编写应用程序来处理从 YAML 文档加载的标量和序列,但这不是自动的,几乎肯定会反映在文档中。

由于您已经有一个更高级别的序列,只需扩展它。

- name: Register env Type
  shell: facter configured_setup
  register: setup

- name: transparency tasks
  shell: {{some_script}} -t -a {{hosts}} -i {{inventory_hostname}}
  register: test
  when: setup.stdout == "something"

- name: fetch group_vars
  fetch:
    src: { "{{ item }}", when: setup.stdout == "something" }
    dest: "{{group_vars}}"
    flat: yes
  with_items:
    - "{{ test.stdout_lines[0] }}"
    - "{{ test.stdout_lines[1] }}"

- name: fetch group_vars2
  fetch:
    src: { filename, when setup.stdout =="something else" }
    dest: "{{group_vars}}"
    flat: yes
  with_items:
    - "{{ test.stdout_lines[0] }}"
    - "{{ test.stdout_lines[1] }}"

你或许可以通过使用 YAML 的锚点和merge 来减少重复性:

- name: Register env Type
  shell: facter configured_setup
  register: setup

- name: transparency tasks
  shell: {{some_script}} -t -a {{hosts}} -i {{inventory_hostname}}
  register: test
  when: setup.stdout == "something"

- &fetchtask
  name: fetch group_vars
  fetch: &fetchsrc
    src: { "{{ item }}", when: setup.stdout == "something" }
    dest: "{{group_vars}}"
    flat: yes
  with_items:
    - "{{ test.stdout_lines[0] }}"
    - "{{ test.stdout_lines[1] }}"

- <<: *fetchtask
  name: fetch group_vars2
  fetch:
    <<: *fetchsrc
    src: { filename, when setup.stdout =="something else" }

Ansible 在将文档交给 YAML 解析器之前可能会扩展 {{...}},否则“透明任务”中 shell 的值会引发错误。但是您可能仍然应该像使用 dest 的值一样引用它

【讨论】:

    【解决方案2】:

    所以我最终这样做了(这是有效的):

      - name: fetch group_vars test
        fetch:
          src: "{{ item }}"
          dest: "{{group_vars}}"
          flat: yes
        with_items:
          - "{{ test.stdout_lines[0] }}"
          - "{{ test.stdout_lines[1] }}"
        when: setup.stdout == "something" and {{something_else}} == True
    

    我还注意到 ansible 中可能存在与寄存器相关的错误。 使用when语句时,即使不满足条件,register语句也会生效:

      - name: test tasks something enabled
        shell: /tmp/{{populate_script}} -u -a {{hosts}} -r
        register: variable
        when: setup.stdout == "test" and something == True
    
      - name: test tasks something disabled
        shell: /tmp/{{populate_script}} -u -a {{hosts}}
        register: variable
        when: setup.stdout == "test" and something == False
    

    只会满足其中一个条件,如果满足第一个条件,则第二个条件将覆盖“变量”

    【讨论】:

    • 您不应该在 when 中使用 Jinja2 表达式分隔符。为什么你认为register 应该被忽略?条件确定是否要运行操作。 register 在任务级别声明。甚至跳过的任务也会记录它们的输出,从而有效地覆盖以前的值。这就是它的工作原理。
    猜你喜欢
    • 1970-01-01
    • 2012-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-11
    • 2013-07-29
    • 2017-10-05
    • 1970-01-01
    相关资源
    最近更新 更多