Skip to content

Commit c12f665

Browse files
committed
update ssm_document module
1 parent dbf0b8f commit c12f665

File tree

2 files changed

+40
-6
lines changed

2 files changed

+40
-6
lines changed

plugins/connection/aws_ssm.py

+35-4
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@
298298
from typing import Optional
299299
from typing import NoReturn
300300
from typing import Tuple
301+
from typing import ByteString
301302

302303
try:
303304
import boto3
@@ -339,7 +340,7 @@ def wrapped(self, *args, **kwargs):
339340
for attempt in range(remaining_tries):
340341
try:
341342
return_tuple = func(self, *args, **kwargs)
342-
self._vvvv(f"ssm_retry: (success) {to_text(return_tuple)}")
343+
self._vvvv(f"ssm_retry: (end of process) {to_text(return_tuple)}")
343344
break
344345

345346
except (AnsibleConnectionFailure, Exception) as e:
@@ -662,7 +663,33 @@ def poll(self, label: str, cmd: str) -> NoReturn:
662663
raise AnsibleConnectionFailure(f"{label} command '{cmd}' timeout on host: {self.instance_id}")
663664
yield self.poll_stdout()
664665

665-
def exec_communicate(self, cmd: str, mark_start: str, mark_begin: str, mark_end: str) -> Tuple[int, str, str]:
666+
def _check_become_success(self, cmd: str) -> ByteString:
667+
become_output = b''
668+
for result in self.poll("ENSURE_BECOME", cmd):
669+
if not result:
670+
continue
671+
become_output += self._stdout.readline()
672+
if not self.become.check_success(become_output) and not self.become.check_password_prompt(become_output):
673+
return ByteString
674+
675+
def ensure_become(self, cmd: str, sudoable: bool) -> ByteString:
676+
"""When become is activated we ensure that the become step has succeed and if not the process may be waiting for
677+
the password to be provided. In this case we will send it to the stdin
678+
"""
679+
become_output = b''
680+
if self.become and self.become.expect_prompt() and sudoable:
681+
try:
682+
become_output = self._check_become_success(cmd)
683+
except AnsibleConnectionFailure:
684+
# Inject password into command
685+
if not self.become.check_success(become_output):
686+
become_pass = self.become.get_option('become_pass', playcontext=self._play_context)
687+
self._session.stdin.write(to_bytes(become_pass, errors='surrogate_or_strict') + b'\n')
688+
become_output = self._check_become_success(cmd)
689+
return become_output
690+
691+
692+
def exec_communicate(self, cmd: str, mark_start: str, mark_begin: str, mark_end: str, sudoable: bool) -> Tuple[int, str, str]:
666693
"""Interact with session.
667694
Read stdout between the markers until 'mark_end' is reached.
668695
@@ -673,7 +700,7 @@ def exec_communicate(self, cmd: str, mark_start: str, mark_begin: str, mark_end:
673700
:returns: A tuple with the return code, the stdout and the stderr content.
674701
"""
675702
# Read stdout between the markers
676-
stdout = ""
703+
stdout = to_text(self.ensure_become(cmd, sudoable))
677704
win_line = ""
678705
begin = False
679706
returncode = None
@@ -708,6 +735,7 @@ def exec_communicate(self, cmd: str, mark_start: str, mark_begin: str, mark_end:
708735
def exec_command(self, cmd: str, in_data: bool = None, sudoable: bool = True) -> Tuple[int, str, str]:
709736
"""run a command on the ssm host"""
710737

738+
self._v(f"[_exec_command] => {cmd} - sudoable = {sudoable}")
711739
super().exec_command(cmd, in_data=in_data, sudoable=sudoable)
712740

713741
self._vvv(f"EXEC: {to_text(cmd)}")
@@ -727,7 +755,7 @@ def exec_command(self, cmd: str, in_data: bool = None, sudoable: bool = True) ->
727755
for chunk in chunks(cmd, 1024):
728756
self._session.stdin.write(to_bytes(chunk, errors="surrogate_or_strict"))
729757

730-
return self.exec_communicate(cmd, mark_start, mark_begin, mark_end)
758+
return self.exec_communicate(cmd, mark_start, mark_begin, mark_end, sudoable)
731759

732760
def _prepare_terminal(self):
733761
"""perform any one-time terminal settings"""
@@ -1016,6 +1044,7 @@ def _file_transport_command(self, in_path, out_path, ssm_action):
10161044
def put_file(self, in_path, out_path):
10171045
"""transfer a file from local to remote"""
10181046

1047+
self._v("put_file")
10191048
super().put_file(in_path, out_path)
10201049

10211050
self._vvv(f"PUT {in_path} TO {out_path}")
@@ -1027,13 +1056,15 @@ def put_file(self, in_path, out_path):
10271056
def fetch_file(self, in_path, out_path):
10281057
"""fetch a file from remote to local"""
10291058

1059+
self._v("fetch_file")
10301060
super().fetch_file(in_path, out_path)
10311061

10321062
self._vvv(f"FETCH {in_path} TO {out_path}")
10331063
return self._file_transport_command(in_path, out_path, "get")
10341064

10351065
def close(self):
10361066
"""terminate the connection"""
1067+
self._v("close")
10371068
if self._session_id:
10381069
self._vvv(f"CLOSING SSM CONNECTION TO: {self.instance_id}")
10391070
if self._has_timeout:

plugins/modules/ssm_document.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,11 @@ def update_document(
436436
) != existing_document.get(aws_key):
437437
params[aws_key] = document_parameters.get(ansible_key)
438438

439-
if params and document_parameters.get("attachments"):
440-
params["Attachments"] = document_parameters.get("attachments")
439+
if document_parameters.get("attachments"):
440+
ansible_attachments = sorted([x.get("name") for x in document_parameters.get("attachments")])
441+
aws_attachments = sorted([x.get("Name") for x in existing_document.get("AttachmentsInformation")])
442+
if aws_attachments != ansible_attachments:
443+
params["Attachments"] = document_parameters.get("attachments")
441444

442445
changed = False
443446
ssm_document = None

0 commit comments

Comments
 (0)