1010import os
1111import tempfile
1212
13+ from ansible .module_utils .common .text .converters import to_bytes , to_text
1314from ansible .plugins .action import ActionBase
15+ from ansible .plugins .loader import lookup_loader
1416from ansible .utils .display import Display
1517from ansible .utils .hashing import checksum
1618
1719
1820display = Display ()
1921
22+ # def _get_binary_src_file(self, src):
23+
24+ # if not os.path.exists(source):
25+ # raise ValueError("path specified in src not found")
26+
27+ # return source
28+
29+ # def _handle_src_option(self, convert_data=True):
30+ # else:
31+ # source = self._loader.path_dwim_relative(working_path, "templates", src)
32+ # if not source:
33+ # source = self._loader.path_dwim_relative(working_path, src)
34+
35+ # if not os.path.exists(source):
36+ # raise AnsibleError("path specified in src not found")
37+
38+ # try:
39+ # with open(source, "r") as f:
40+ # template_data = to_text(f.read())
41+ # except IOError as e:
42+ # raise AnsibleError(
43+ # "unable to load src file {0}, I/O error({1}): {2}".format(
44+ # source, e.errno, e.strerror
45+ # )
46+ # )
47+
48+ # # Create a template search path in the following order:
49+ # # [working_path, self_role_path, dependent_role_paths, dirname(source)]
50+ # searchpath = [working_path]
51+ # if self._task._role is not None:
52+ # searchpath.append(self._task._role._role_path)
53+ # if hasattr(self._task, "_block:"):
54+ # dep_chain = self._task._block.get_dep_chain()
55+ # if dep_chain is not None:
56+ # for role in dep_chain:
57+ # searchpath.append(role._role_path)
58+ # searchpath.append(os.path.dirname(source))
59+ # self._templar.environment.loader.searchpath = searchpath
60+ # self._task.args["src"] = self._templar.template(template_data)
61+
2062
2163class ActionModule (ActionBase ):
2264
@@ -28,6 +70,20 @@ def __init__(self, *args, **kwargs):
2870 def run (self , tmp = None , task_vars = None ):
2971 result = super (ActionModule , self ).run (task_vars = task_vars )
3072
73+ if "changed" not in result :
74+ result ["changed" ] = False
75+
76+ persistent_connection = self ._play_context .connection .split ("." )[- 1 ]
77+ if persistent_connection != "network_cli" :
78+ # It is supported only with network_cli
79+ return {
80+ "failed" : True ,
81+ "msg" : (
82+ "connection type %s is not valid for net_put module, please use fully "
83+ "qualified name of network_cli connection type" % self ._play_context .connection
84+ ),
85+ }
86+
3187 try :
3288 self ._src = self ._task .args .get ("src" )
3389 except KeyError as exc :
@@ -42,21 +98,31 @@ def run(self, tmp=None, task_vars=None):
4298 self ._mode = self ._task .args .get ("mode" , "binary" )
4399 self ._protocol = self ._task .args .get ("protocol" , "scp" )
44100
45- self ._src_real_file = self ._loader .get_real_file (self ._src , decrypt = self ._decrypt )
101+ working_path = self ._get_working_path ()
102+ if os .path .isabs (self ._src ):
103+ self ._src_real_file = self ._loader .get_real_file (self ._src , decrypt = self ._decrypt )
104+ elif self ._loader .path_dwim_relative (working_path , "templates" , self ._src ) != "" :
105+ self ._src_real_file = self ._loader .path_dwim_relative (
106+ working_path , "templates" , self ._src
107+ )
108+ elif self ._loader .path_dwim_relative (working_path , self ._src ):
109+ self ._src_real_file = self ._loader .path_dwim_relative (working_path , self ._src )
46110
47111 try :
48112 fetched_fd , fetched_fp = tempfile .mkstemp (prefix = "" )
49113 rendered_fd , rendered_fp = tempfile .mkstemp (prefix = "" )
50114
51- if self . _mode == "binary" :
115+ if "binary" == self . _mode :
52116 self ._rendered_real_file = self ._src_real_file
53- elif self . _mode == "text" :
117+ elif "text" == self . _mode :
54118 self ._rendered_real_file = rendered_fp
55- template_result = self ._execute_module (
56- module_name = "ansible.builtin.template" ,
57- module_args = {"dest" : self ._rendered_real_file , "src" : self ._src_real_file },
58- task_vars = task_vars ,
119+ lookup = lookup_loader .get (
120+ "ansible.builtin.template" , loader = self ._loader , templar = self ._templar
59121 )
122+ template_result = lookup .run ([self ._src ], variables = task_vars )
123+
124+ with open (self ._rendered_real_file , "wb" ) as fh :
125+ fh .write (to_bytes (template_result [0 ]))
60126 self ._rendered_checksum = checksum (self ._rendered_real_file )
61127
62128 display .vv (
@@ -65,29 +131,46 @@ def run(self, tmp=None, task_vars=None):
65131 )
66132
67133 try :
68- self ._connection ._ssh_type_conn . fetch_file (self ._dest , fetched_fp , self ._protocol )
134+ self ._connection .get_file (self ._dest , fetched_fp , self ._protocol )
69135 except Exception as exc :
136+ error = to_text (exc ).lower ()
70137 if not (
71- "Error receiving information about file" in exc . message
72- and "No such file or directory" in exc . message
138+ "error receiving information about file" in error
139+ or "no such file or directory" in error
73140 ):
74141 raise exc
75- display .vv ("The file is not present on the remote device" )
76- finally :
77- self ._connection ._ssh_type_conn .reset ()
78- self ._dest_checksum = checksum (fetched_fp )
79-
80- try :
81- if self ._dest_checksum != self ._rendered_checksum :
82- self ._connection ._ssh_type_conn .put_file (
142+ self ._dest_checksum = checksum (fetched_fp )
143+
144+ if self ._dest_checksum != self ._rendered_checksum :
145+ result ["changed" ] = True
146+
147+ if self ._task ._diff :
148+ if "binary" == self ._mode :
149+ result ["diff" ] = {
150+ "before" : self ._dest_checksum ,
151+ "after" : self ._rendered_checksum ,
152+ }
153+ elif "text" == self ._mode :
154+ with open (fetched_fp , "r" ) as fh :
155+ result ["diff" ] = {
156+ "before" : to_text (fh .read ()),
157+ "after" : template_result [0 ],
158+ }
159+
160+ if not self ._task .check_mode :
161+ self ._connection .copy_file (
83162 self ._loader .get_real_file (self ._rendered_real_file ),
84163 self ._dest ,
85164 self ._protocol ,
86165 )
87- finally :
88- self ._connection ._ssh_type_conn .reset ()
89166
90167 return result
91168 finally :
92169 os .remove (fetched_fp )
93170 os .remove (rendered_fp )
171+
172+ def _get_working_path (self ):
173+ cwd = self ._loader .get_basedir ()
174+ if self ._task ._role is not None :
175+ cwd = self ._task ._role ._role_path
176+ return cwd
0 commit comments