自动在Ansible中创建不存在的目录的简单方法是什么


117

在我的Ansible剧本中,我需要多次在其中创建文件

 - name: Copy file
   template:
     src: code.conf.j2
     dest: "{{project_root}}/conf/code.conf"

现在很多时候confdir不存在。然后,我必须创建更多任务以首先创建该目录。

如果不存在某些选项,有什么简单的方法可以自动创建目录



我不能相信这仍然是ansible 2.9中的问题。这些模块的创建目录切换(默认为关闭)有多难。这样可以节省剧本中的大量杂物,而不必像下面的答案那样处理预测试
krad

Answers:


138

现在,这是唯一的方法

- name: Ensures {{project_root}}/conf dir exists
  file: path={{project_root}}/conf state=directory
- name: Copy file
  template:
    src: code.conf.j2
    dest: "{{project_root}}/conf/code.conf"

2
我认为保证是正确的词。确保:“积极地告诉某人以消除任何疑问”,确保:“确保(某事)会发生或确实如此”。
丹尼尔·康普顿

似乎可以检查目录是否存在,但似乎无法创建目录。
马特

8
应该注意,您可能想添加recurse=yesfile呼叫中以获取mkdir -p类型行为
Mitch

1
另一个可能有用的难题是特定dirnameAnsible的过滤器,以获取包含文件的目录。
卡斯珀

1
@radtek文件模块已经使用state = directory进行了此操作。如果无法确保建议的文件路径指向目录,则会失败。
亚历山大·贾丁

20

为确保使用完整路径成功,请使用recurse = yes

- name: ensure custom facts directory exists
    file: >
      path=/etc/ansible/facts.d
      recurse=yes
      state=directory

2
根据文档(和我的测试),总是创建子目录,并且recurse=yes仅递归地应用权限。但是,文档指出,这是从v1.7开始自动发生的,因此recurse可能已经过时了。
To마SE 2016年

16

如果您正在运行Ansible> = 2.0,那么还有dirname过滤器可用于提取路径的目录部分。这样,您可以只使用一个变量来保存整个路径,以确保这两个任务永不同步。

因此,例如,如果您dest_path在这样的变量中定义了剧本,则可以重复使用相同的变量:

- name: My playbook
  vars:
    dest_path: /home/ubuntu/some_dir/some_file.txt
  tasks:

    - name: Make sure destination dir exists
      file:
        path: "{{ dest_path | dirname }}"
        state: directory
        recurse: yes

    # now this task is always save to run no matter how dest_path get's changed arround
    - name: Add file or template to remote instance
      template: 
        src: foo.txt.j2
        dest: "{{ dest_path }}"

1
尽管此解决方案仍然很冗长,但我认为它与作者的意图最接近。如果有像Salt这样的简单“ makedirs”参数,我会喜欢的docs.saltstack.com/en/latest/ref/states/all/…–
lsh

7

据我所知,这是唯一的方法可以做的是通过使用state=directory选项。虽然template模块支持大多数copy选项,而模块又支持大多数file选项,但您不能使用类似的选项state=directory。而且,这将非常令人困惑(这是否意味着这{{project_root}}/conf/code.conf是一个目录?或者{{project_root}}/conf/应该首先创建该目录。

因此,我认为如果不添加先前的file任务,现在不可能实现。

- file: 
    path: "{{project_root}}/conf"
    state: directory
    recurse: yes

7

根据最新文档,在将状态设置为目录时,您无需使用参数递归来创建父目录,文件模块将负责处理。

- name: create directory with parent directories
  file:
    path: /data/test/foo
    state: directory

这足以创建父目录数据并使用foo 测试

请参阅参数说明-“ 状态http://docs.ansible.com/ansible/latest/modules/file_module.html


请在此处添加解决方案,而不是将来可能会断开的链接。
Ignacio Ara

@IgnacioAra感谢您的宝贵意见,我已经添加了解决方案。
Alby


1

如果该目录不存在,复制模块将创建该目录。在这种情况下,它创建了resolve.conf.d目录

- name: put fallback_dns.conf in place                                                                 
  copy:                                                                                                
    src: fallback_dns.conf                                                                             
    dest: /etc/systemd/resolved.conf.d/                                                                
    mode: '0644'                                                                                       
    owner: root                                                                                        
    group: root                                                                                        
  become: true                                                                                         
  tags: testing
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.