net_put module: add default mode to copy binary files (#41476)

* add default mode to copy binary files

* sanity fix

* add version for new options
This commit is contained in:
Deepak Agrawal 2018-06-20 16:02:49 +05:30 committed by GitHub
parent 2e68811c34
commit e91cee1a31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 70 additions and 17 deletions

View file

@ -42,6 +42,15 @@ options:
- Filename from src and at default directory of user shell on
network_os.
required: no
mode:
description:
- Set the file transfer mode. If mode is set to 'template' then src
file will go through jinja2 template engine to replace any vars if
present in src file. If mode is set to 'binary' then file will be
copied as it is to destination device.
default: binary
choices: ['binary', 'template']
version_added: "2.7"
requirements:
- "scp"

View file

@ -50,18 +50,13 @@ class ActionModule(ActionBase):
result['msg'] = ('please use network_cli connection type for net_put module')
return result
src_file_path_name = self._task.args.get('src')
try:
self._handle_template()
except ValueError as exc:
return dict(failed=True, msg=to_text(exc))
try:
src = self._task.args.get('src')
except KeyError as exc:
return {'failed': True, 'msg': 'missing required argument: %s' % exc}
src_file_path_name = src
# Get destination file if specified
dest = self._task.args.get('dest')
@ -70,22 +65,38 @@ class ActionModule(ActionBase):
if proto is None:
proto = 'scp'
sock_timeout = play_context.timeout
# Get mode if set
mode = self._task.args.get('mode')
if mode is None:
mode = 'binary'
# Now src has resolved file write to disk in current diectory for scp
filename = str(uuid.uuid4())
cwd = self._loader.get_basedir()
output_file = cwd + '/' + filename
with open(output_file, 'w') as f:
f.write(src)
if mode == 'template':
try:
self._handle_template()
except ValueError as exc:
return dict(failed=True, msg=to_text(exc))
# Now src has resolved file write to disk in current diectory for scp
src = self._task.args.get('src')
filename = str(uuid.uuid4())
cwd = self._loader.get_basedir()
output_file = cwd + '/' + filename
with open(output_file, 'w') as f:
f.write(src)
else:
try:
output_file = self._get_binary_src_file(src)
except ValueError as exc:
return dict(failed=True, msg=to_text(exc))
if socket_path is None:
socket_path = self._connection.socket_path
conn = Connection(socket_path)
sock_timeout = conn.get_option('persistent_command_timeout')
if dest is None:
dest = src_file_path_name
try:
out = conn.copy_file(
source=output_file, destination=dest,
@ -101,8 +112,10 @@ class ActionModule(ActionBase):
result['failed'] = True
result['msg'] = ('Exception received : %s' % exc)
# Cleanup tmp file expanded wih ansible vars
os.remove(output_file)
if mode == 'template':
# Cleanup tmp file expanded wih ansible vars
os.remove(output_file)
result['changed'] = True
return result
@ -165,3 +178,18 @@ class ActionModule(ActionBase):
raise AnsibleError('ansible_network_os must be specified on this host to use platform agnostic modules')
return network_os
def _get_binary_src_file(self, src):
working_path = self._get_working_path()
if os.path.isabs(src) or urlsplit('src').scheme:
source = src
else:
source = self._loader.path_dwim_relative(working_path, 'templates', src)
if not source:
source = self._loader.path_dwim_relative(working_path, src)
if not os.path.exists(source):
raise ValueError('path specified in src not found')
return source

View file

@ -31,4 +31,20 @@
that:
- result.changed == true
- name: copy file with non-ascii characters to ios in template mode(Fail case)
net_put:
src: nonascii.bin
mode: 'template'
register: result
ignore_errors: true
- name: copy file with non-ascii characters to ios in default mode(binary)
net_put:
src: nonascii.bin
register: result
- assert:
that:
- result.changed == true
- debug: msg="END ios cli/net_put.yaml on connection={{ ansible_connection }}"