-3

I want to write an Ansible task to copy file from files directory to templates directory.

For example, I have an Ansible role named data and inside this role's directory

~/data$ tree
.
├── defaults
├── tasks
├── templates
└── files
    └── application.j2

So I have a file inside the files directory named application.j2

I want to copy this file application.j2 into the templates directory using an Ansible task.

I've tried to use the below task in the src: path I use files/application.j2 but I don't know what I should write in dest: path.

- name: Transfer File.
   copy:
    src: "{{ item }}"
    dest: 
  with_fileglob:
    - "files/application.j2"

Ansible: How to copy file from files directory to templates directory in a role directory?

U880D
  • 8,601
  • 6
  • 24
  • 40
zizou
  • 1
  • 2
  • Was this question not already answered? As far as I remember it was recommended to use `mv` and highlighted that Ansible is not intended for altering the code base of the files it is executing itself, means the task files, playbook, templates, etc. – U880D May 26 '23 at 07:57
  • could you provide me with this – zizou May 26 '23 at 08:00
  • Since the question text is a copy a paste from an other question, do you mean the link where it was copied from? Or do you mean the comments where it was answered? Furthermore, what about to use the `mv` command? – U880D May 26 '23 at 08:02
  • ok how to use mv command in local role directory can you provide me with task mv file in local – zizou May 26 '23 at 08:10
  • Do you mean like `mv files/app* templates/` or `cp files/app* templates/`? – U880D May 26 '23 at 08:12
  • ok like this but task in ansible . i want to copyy file between same ansible role directory – – zizou May 26 '23 at 08:19
  • This is a duplicate of https://stackoverflow.com/questions/76333200/ansible-task-to-copy-file-from-files-directory-to-templates-directory-in-a-role?noredirect=1#comment134606460_76333200 Please respect site rules and do not ask the same question twice. Edit your original question. – Zeitounator May 26 '23 at 14:53

2 Answers2

1

Q: "Copy files from files directory to templates directory in a role."

Given the project for testing

shell> pwd
/scratch/tmp7/test-359
shell> tree .
.
├── ansible.cfg
├── hosts
├── pb.yml
├── roles
│   └── data
│       ├── defaults
│       ├── files
│       │   └── application.j2
│       ├── tasks
│       └── templates
├── roles2
│   └── roleX
└── roles3
    └── roleY

A: I read this question as: "What is the directory of a role?"

If you're running a task in a role you can use the special variable role_path. But, this is not the case here. You want to copy the files inside the roles from a task in a playbook. Declare a dictionary with the roles and files you want to transfer between the directories files and templates

  transfer_files:
    data:
      - application.j2

There might be more directories in DEFAULT_ROLES_PATH. For example,

shell> grep roles_path ansible.cfg 
roles_path = $PWD/roles:$PWD/roles2:$PWD/roles3

Get the variable

  my_roles_path: "{{ lookup('config', 'DEFAULT_ROLES_PATH') }}"

gives

  my_roles_path:
  - /scratch/tmp7/test-359/roles
  - /scratch/tmp7/test-359/roles2
  - /scratch/tmp7/test-359/roles3

Find all roles

    - find:
        paths: "{{ my_roles_path }}"
        file_type: directory
        depth: 1
      register: my_roles_out

and declare the variables

  my_roles: "{{ my_roles_out.files|map(attribute='path') }}"
  my_roles_dict: "{{ dict(my_roles|map('basename')|
                          zip(my_roles|map('dirname'))) }}"

gives

  my_roles:
  - /scratch/tmp7/test-359/roles/data
  - /scratch/tmp7/test-359/roles2/roleX
  - /scratch/tmp7/test-359/roles3/roleY

  my_roles_dict:
    data: /scratch/tmp7/test-359/roles
    roleX: /scratch/tmp7/test-359/roles2
    roleY: /scratch/tmp7/test-359/roles3

Now, you can copy the file(s)

    - copy:
        src: "{{ role_path }}/files/{{ item.1 }}"
        dest: "{{ role_path }}/templates/{{ item.1 }}"
      loop: "{{ transfer_files|dict2items|subelements('value') }}"
      vars:
        role_path: "{{ my_roles_dict[item.0.key] }}/{{ item.0.key }}"

gives

shell> tree .
.
├── ansible.cfg
├── hosts
├── pb.yml
├── roles
│   └── data
│       ├── defaults
│       ├── files
│       │   └── application.j2
│       ├── tasks
│       └── templates
│           └── application.j2   <-- from files
├── roles2
│   └── roleX
└── roles3
    └── roleY

Example of a complete playbook for testing

- hosts: localhost

  vars:

    my_roles_path: "{{ lookup('config', 'DEFAULT_ROLES_PATH') }}"
    my_roles: "{{ my_roles_out.files|map(attribute='path') }}"
    my_roles_dict: "{{ dict(my_roles|map('basename')|
                            zip(my_roles|map('dirname'))) }}"

    transfer_files:
      data:
        - application.j2

  tasks:

    - debug:
        var: my_roles_path

    - find:
        paths: "{{ my_roles_path }}"
        file_type: directory
        depth: 1
      register: my_roles_out

    - debug:
        var: my_roles
    - debug:
        var: my_roles_dict

    - copy:
        src: "{{ role_path }}/files/{{ item.1 }}"
        dest: "{{ role_path }}/templates/{{ item.1 }}"
      loop: "{{ transfer_files|dict2items|subelements('value') }}"
      vars:
        role_path: "{{ my_roles_dict[item.0.key] }}/{{ item.0.key }}"
Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63
0

Let's assume one like to

  • Copy files with patterns between different folders
  • Let the task run on the Ansible Control Node only

A minimal example playbook

---
- hosts: localhost 
  become: false
  gather_facts: false

  tasks:

  - name: Copy each file that matches the given pattern
    copy:
      src: "{{ item }}"
      dest: "templates/{{ item.split('.') | first | basename }}.j2"
    with_fileglob:
      - "files/app*.j2"

will result into the requested output.

Similar Q&A

For a more detailed explanation see the answer under

U880D
  • 8,601
  • 6
  • 24
  • 40
  • no i didn't mean this . i want to copyy file between same ansible role directory – zizou May 26 '23 at 08:17
  • That's exactly what the task is doing. Can you explain in more detail why do you think it is not? Furthermore, you've provided an example task with some missing functionality which I've just extended to make it work. – U880D May 26 '23 at 08:22
  • this task it will be beside another tasks so i cant wirte - hosts: localhost become: false gather_facts: false – zizou May 26 '23 at 08:40
  • I've just provided a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). Maybe you can have a look into the article. – U880D May 26 '23 at 08:50
  • Furthermore regarding "_will be beside another tasks so I cant write_", technically it would be possible, so of course you could, see [Playbook execution](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_intro.html#playbook-execution). Maybe you can have a look into the documention. – U880D May 26 '23 at 08:51
  • Regarding "_I cant write - hosts: localhost_" and since you like and need to [Control where tasks run: delegation and local actions](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_delegation.html), maybe you can have a look into the documentation and use just `delegate_to: localhost run_one: true`. – U880D May 26 '23 at 08:52