Add example of templating inline using copy module (#19752)

* Add example of templating inline using copy module

The **copy** module documentation implies that `content:` only works
for 'simple values' and for complex stuff you need the **template**
module, but that is an understatement. You can use **copy** to template
anything you desire.

So I changed the wording, added an example, and also added a note
to the template module that the **copy** module could be used for
'inline templating'.

This fixes #19741.
This commit is contained in:
Dag Wieers 2017-07-23 07:12:31 +02:00 committed by Toshio Kuratomi
parent 4e8b28e404
commit be1c517f4d
3 changed files with 75 additions and 70 deletions

View file

@ -22,12 +22,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
'status': ['stableinterface'], 'status': ['stableinterface'],
'supported_by': 'core'} 'supported_by': 'core'}
DOCUMENTATION = r'''
DOCUMENTATION = '''
--- ---
module: copy module: copy
version_added: "historical" version_added: "historical"
short_description: Copies files to remote locations. short_description: Copies files to remote locations
description: description:
- The C(copy) module copies a file from the local or remote machine to a location on the remote machine. - The C(copy) module copies a file from the local or remote machine to a location on the remote machine.
Use the M(fetch) module to copy files from remote locations to the local box. Use the M(fetch) module to copy files from remote locations to the local box.
@ -41,69 +40,58 @@ options:
with "/", only inside contents of that directory are copied to destination. with "/", only inside contents of that directory are copied to destination.
Otherwise, if it does not end with "/", the directory itself with all contents Otherwise, if it does not end with "/", the directory itself with all contents
is copied. This behavior is similar to Rsync. is copied. This behavior is similar to Rsync.
required: false
default: null
aliases: []
content: content:
version_added: "1.1"
description: description:
- When used instead of 'src', sets the contents of a file directly to the specified value. - When used instead of 'src', sets the contents of a file directly to the specified value.
This is for simple values, for anything complex or with formatting please switch to the template module. For anything advanced or with formatting also look at the template module.
required: false version_added: "1.1"
default: null
dest: dest:
description: description:
- Remote absolute path where the file should be copied to. If src is a directory, - Remote absolute path where the file should be copied to. If C(src) is a directory,
this must be a directory too. this must be a directory too.
required: true required: yes
default: null
backup: backup:
description: description:
- Create a backup file including the timestamp information so you can get - Create a backup file including the timestamp information so you can get
the original file back if you somehow clobbered it incorrectly. the original file back if you somehow clobbered it incorrectly.
type: bool
default: 'no'
version_added: "0.7" version_added: "0.7"
required: false
choices: [ "yes", "no" ]
default: "no"
force: force:
description: description:
- the default is C(yes), which will replace the remote file when contents - the default is C(yes), which will replace the remote file when contents
are different than the source. If C(no), the file will only be transferred are different than the source. If C(no), the file will only be transferred
if the destination does not exist. if the destination does not exist.
version_added: "1.1" type: bool
required: false default: 'yes'
choices: [ "yes", "no" ]
default: "yes"
aliases: [ "thirsty" ] aliases: [ "thirsty" ]
version_added: "1.1"
directory_mode: directory_mode:
description: description:
- When doing a recursive copy set the mode for the directories. If this is not set we will use the system - When doing a recursive copy set the mode for the directories. If this is not set we will use the system
defaults. The mode is only set on directories which are newly created, and will not affect those that defaults. The mode is only set on directories which are newly created, and will not affect those that
already existed. already existed.
required: false
version_added: "1.5" version_added: "1.5"
remote_src: remote_src:
description: description:
- If False, it will search for src at originating/master machine, if True it will go to the remote/target machine for the src. Default is False. - If C(no), it will search for src at originating/master machine.
- Currently remote_src does not support recursive copying. - If C(yes), it will go to the remote/target machine for the src. Default is False.
choices: [ "True", "False" ] - Currently C(remote_src) does not support recursive copying.
required: false type: bool
default: "False" default: 'no'
version_added: "2.0" version_added: "2.0"
follow: follow:
required: false description:
default: "no" - This flag indicates that filesystem links in the destination, if they exist, should be followed.
choices: [ "yes", "no" ] type: bool
default: 'no'
version_added: "1.8" version_added: "1.8"
description:
- 'This flag indicates that filesystem links in the destination, if they exist, should be followed.'
local_follow: local_follow:
required: false
default: "yes"
choices: [ "yes", "no" ]
version_added: "2.4"
description: description:
- 'This flag indicates that filesystem links in the source tree, if they exist, should be followed.' - This flag indicates that filesystem links in the source tree, if they exist, should be followed.
type: bool
default: 'yes'
version_added: "2.4"
extends_documentation_fragment: extends_documentation_fragment:
- files - files
- validate - validate
@ -117,7 +105,7 @@ notes:
- For Windows targets, use the M(win_copy) module instead. - For Windows targets, use the M(win_copy) module instead.
''' '''
EXAMPLES = ''' EXAMPLES = r'''
# Example from Ansible Playbooks # Example from Ansible Playbooks
- copy: - copy:
src: /srv/myfiles/foo.conf src: /srv/myfiles/foo.conf
@ -132,7 +120,7 @@ EXAMPLES = '''
dest: /etc/foo.conf dest: /etc/foo.conf
owner: foo owner: foo
group: foo group: foo
mode: "u=rw,g=r,o=r" mode: u=rw,g=r,o=r
# Another symbolic mode example, adding some permissions and removing others # Another symbolic mode example, adding some permissions and removing others
- copy: - copy:
@ -140,7 +128,7 @@ EXAMPLES = '''
dest: /etc/foo.conf dest: /etc/foo.conf
owner: foo owner: foo
group: foo group: foo
mode: "u+rw,g-wx,o-rwx" mode: u+rw,g-wx,o-rwx
# Copy a new "ntp.conf file into place, backing up the original if it differs from the copied version # Copy a new "ntp.conf file into place, backing up the original if it differs from the copied version
- copy: - copy:
@ -155,41 +143,57 @@ EXAMPLES = '''
- copy: - copy:
src: /mine/sudoers src: /mine/sudoers
dest: /etc/sudoers dest: /etc/sudoers
validate: 'visudo -cf %s' validate: visudo -cf %s
# Copy a "sudoers" file on the remote machine for editing # Copy a "sudoers" file on the remote machine for editing
- copy: - copy:
remote_src: true
src: /etc/sudoers src: /etc/sudoers
dest: /etc/sudoers.edit dest: /etc/sudoers.edit
remote_src: yes
validate: visudo -cf %s
# Create a CSV file from your complete inventory using an inline template
- hosts: all
tasks:
- copy:
content: |
HOSTNAME;IPADDRESS;FQDN;OSNAME;OSVERSION;PROCESSOR;ARCHITECTURE;MEMORY;
{% for host in hostvars %}
{% set vars = hostvars[host|string] %}
{{ vars.ansible_hostname }};{{ vars.remote_host }};{{ vars.ansible_fqdn }};{{ vars.ansible_distribution }};{{ vars.ansible_distribution_version }};{{ vars.ansible_processor[1] }};{{ vars.ansible_architecture }};{{ (vars.ansible_memtotal_mb/1024)|round|int }}; # NOQA
{% endfor %}
dest: /some/path/systems.csv
backup: yes
run_once: yes
delegate_to: localhost
''' '''
RETURN = ''' RETURN = r'''
dest: dest:
description: destination file/path description: destination file/path
returned: success returned: success
type: string type: string
sample: "/path/to/file.txt" sample: /path/to/file.txt
src: src:
description: source file used for the copy on the target machine description: source file used for the copy on the target machine
returned: changed returned: changed
type: string type: string
sample: "/home/httpd/.ansible/tmp/ansible-tmp-1423796390.97-147729857856000/source" sample: /home/httpd/.ansible/tmp/ansible-tmp-1423796390.97-147729857856000/source
md5sum: md5sum:
description: md5 checksum of the file after running copy description: md5 checksum of the file after running copy
returned: when supported returned: when supported
type: string type: string
sample: "2a5aeecc61dc98c4d780b14b330e3282" sample: 2a5aeecc61dc98c4d780b14b330e3282
checksum: checksum:
description: sha1 checksum of the file after running copy description: sha1 checksum of the file after running copy
returned: success returned: success
type: string type: string
sample: "6e642bb8dd5c2e027bf21dd923337cbb4214f827" sample: 6e642bb8dd5c2e027bf21dd923337cbb4214f827
backup_file: backup_file:
description: name of backup file created description: name of backup file created
returned: changed and if backup=yes returned: changed and if backup=yes
type: string type: string
sample: "/path/to/file.txt.2015-02-12@22:09~" sample: /path/to/file.txt.2015-02-12@22:09~
gid: gid:
description: group id of the file, after execution description: group id of the file, after execution
returned: success returned: success
@ -199,12 +203,12 @@ group:
description: group of the file, after execution description: group of the file, after execution
returned: success returned: success
type: string type: string
sample: "httpd" sample: httpd
owner: owner:
description: owner of the file, after execution description: owner of the file, after execution
returned: success returned: success
type: string type: string
sample: "httpd" sample: httpd
uid: uid:
description: owner id of the file, after execution description: owner id of the file, after execution
returned: success returned: success
@ -214,7 +218,7 @@ mode:
description: permissions of the target, after execution description: permissions of the target, after execution
returned: success returned: success
type: string type: string
sample: "0644" sample: 0644
size: size:
description: size of the target, after execution description: size of the target, after execution
returned: success returned: success
@ -224,7 +228,7 @@ state:
description: state of the target, after execution description: state of the target, after execution
returned: success returned: success
type: string type: string
sample: "file" sample: file
''' '''
import os import os
@ -270,17 +274,17 @@ def main():
module = AnsibleModule( module = AnsibleModule(
# not checking because of daisy chain to file module # not checking because of daisy chain to file module
argument_spec = dict( argument_spec=dict(
src = dict(required=False, type='path'), src=dict(type='path'),
original_basename = dict(required=False), # used to handle 'dest is a directory' via template, a slight hack original_basename=dict(type='str'), # used to handle 'dest is a directory' via template, a slight hack
content = dict(required=False, no_log=True), content=dict(type='str', no_log=True),
dest = dict(required=True, type='path'), dest=dict(type='path', required=True),
backup = dict(default=False, type='bool'), backup=dict(type='bool', default=False),
force = dict(default=True, aliases=['thirsty'], type='bool'), force=dict(type='bool', default=True, aliases=['thirsty']),
validate = dict(required=False, type='str'), validate=dict(type='str'),
directory_mode = dict(required=False, type='raw'), directory_mode=dict(type='raw'),
remote_src = dict(required=False, type='bool'), remote_src=dict(type='bool'),
local_follow = dict(required=False, type='bool'), local_follow=dict(type='bool'),
), ),
add_file_common_args=True, add_file_common_args=True,
supports_check_mode=True, supports_check_mode=True,

View file

@ -19,12 +19,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
'status': ['stableinterface'], 'status': ['stableinterface'],
'supported_by': 'core'} 'supported_by': 'core'}
DOCUMENTATION = r''' DOCUMENTATION = r'''
--- ---
module: template module: template
version_added: historical version_added: historical
short_description: Templates a file out to a remote server. short_description: Templates a file out to a remote server
description: description:
- Templates are processed by the Jinja2 templating language - Templates are processed by the Jinja2 templating language
(U(http://jinja.pocoo.org/docs/)) - documentation on the template (U(http://jinja.pocoo.org/docs/)) - documentation on the template
@ -51,8 +50,8 @@ options:
description: description:
- Create a backup file including the timestamp information so you can get - Create a backup file including the timestamp information so you can get
the original file back if you somehow clobbered it incorrectly. the original file back if you somehow clobbered it incorrectly.
choices: [ "yes", "no" ] type: bool
default: "no" default: 'no'
newline_sequence: newline_sequence:
description: description:
- Specify the newline sequence to use for templating files. - Specify the newline sequence to use for templating files.
@ -82,15 +81,16 @@ options:
trim_blocks: trim_blocks:
description: description:
- If this is set to True the first newline after a block is removed (block, not variable tag!). - If this is set to True the first newline after a block is removed (block, not variable tag!).
default: "no" type: bool
default: 'no'
version_added: '2.4' version_added: '2.4'
force: force:
description: description:
- the default is C(yes), which will replace the remote file when contents - the default is C(yes), which will replace the remote file when contents
are different than the source. If C(no), the file will only be transferred are different than the source. If C(no), the file will only be transferred
if the destination does not exist. if the destination does not exist.
choices: [ "yes", "no" ] type: bool
default: "yes" default: 'yes'
notes: notes:
- For Windows you can use M(win_template) which uses '\r\n' as C(newline_sequence). - For Windows you can use M(win_template) which uses '\r\n' as C(newline_sequence).
- Including a string that uses a date in the template will result in the template being marked 'changed' each time - Including a string that uses a date in the template will result in the template being marked 'changed' each time
@ -100,6 +100,8 @@ notes:
which changes the variable interpolation markers to [% var %] instead of {{ var }}. which changes the variable interpolation markers to [% var %] instead of {{ var }}.
This is the best way to prevent evaluation of things that look like, but should not be Jinja2. This is the best way to prevent evaluation of things that look like, but should not be Jinja2.
raw/endraw in Jinja2 will not work as you expect because templates in Ansible are recursively evaluated." raw/endraw in Jinja2 will not work as you expect because templates in Ansible are recursively evaluated."
- You can use the C(copy) module with the C(content:) option if you prefer the template inline,
as part of the playbook.
author: author:
- Ansible Core Team - Ansible Core Team
- Michael DeHaan - Michael DeHaan

View file

@ -230,7 +230,6 @@ lib/ansible/modules/files/acl.py
lib/ansible/modules/files/archive.py lib/ansible/modules/files/archive.py
lib/ansible/modules/files/assemble.py lib/ansible/modules/files/assemble.py
lib/ansible/modules/files/blockinfile.py lib/ansible/modules/files/blockinfile.py
lib/ansible/modules/files/copy.py
lib/ansible/modules/files/ini_file.py lib/ansible/modules/files/ini_file.py
lib/ansible/modules/files/iso_extract.py lib/ansible/modules/files/iso_extract.py
lib/ansible/modules/files/replace.py lib/ansible/modules/files/replace.py