Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package aws-efs-utils for openSUSE:Factory 
checked in at 2022-12-03 10:03:29
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/aws-efs-utils (Old)
 and      /work/SRC/openSUSE:Factory/.aws-efs-utils.new.1835 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "aws-efs-utils"

Sat Dec  3 10:03:29 2022 rev:12 rq:1039570 version:1.34.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/aws-efs-utils/aws-efs-utils.changes      
2022-10-20 11:12:00.596055941 +0200
+++ /work/SRC/openSUSE:Factory/.aws-efs-utils.new.1835/aws-efs-utils.changes    
2022-12-03 10:03:37.547236717 +0100
@@ -1,0 +2,14 @@
+Fri Dec  2 11:38:36 UTC 2022 - John Paul Adrian Glaubitz 
<[email protected]>
+
+- Update to version 1.34.3
+  * Fix stunnel constantly restart issue when upgrading
+    from 1.32.1 and before version to latest version
+  * Fix race in stunnel port selection
+  * Disable journal entry fetch from systemctl call
+- from version 1.34.2
+  * Fix potential issue on AL2 when watchdog trying to restart
+    stunnel for the TLS mounts that existing before upgrade
+- from version 1.34.1
+  * Update Amazon Linux 2 platform to use namespaced stunnel5
+
+-------------------------------------------------------------------

Old:
----
  efs-utils-1.33.4.tar.gz

New:
----
  efs-utils-1.34.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ aws-efs-utils.spec ++++++
--- /var/tmp/diff_new_pack.uspgF3/_old  2022-12-03 10:03:38.111239851 +0100
+++ /var/tmp/diff_new_pack.uspgF3/_new  2022-12-03 10:03:38.119239896 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           aws-efs-utils
-Version:        1.33.4
+Version:        1.34.3
 Release:        0
 Summary:        Utilities for using the EFS file systems
 License:        MIT

++++++ efs-utils-1.33.4.tar.gz -> efs-utils-1.34.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/efs-utils-1.33.4/amazon-efs-utils.spec 
new/efs-utils-1.34.3/amazon-efs-utils.spec
--- old/efs-utils-1.33.4/amazon-efs-utils.spec  2022-09-22 07:36:56.000000000 
+0200
+++ new/efs-utils-1.34.3/amazon-efs-utils.spec  2022-12-02 12:17:58.000000000 
+0100
@@ -35,7 +35,7 @@
 %endif
 
 Name      : amazon-efs-utils
-Version   : 1.33.4
+Version   : 1.34.3
 Release   : 1%{platform}
 Summary   : This package provides utilities for simplifying the use of EFS 
file systems
 
@@ -43,13 +43,15 @@
 License   : MIT
 URL       : https://aws.amazon.com/efs
 
-Packager  : Amazon.com, Inc. <http://aws.amazon.com>
-Vendor    : Amazon.com
 
 BuildArch : noarch
 
 Requires  : nfs-utils
+%if 0%{?amzn2}
+Requires  : stunnel5
+%else
 Requires  : stunnel >= 4.56
+%endif
 Requires  : %{python_requires}
 Requires  : openssl >= 1.0.2
 Requires  : util-linux
@@ -135,6 +137,17 @@
 %clean
 
 %changelog
+* Thu Dec 1 2022 Preetham Puneeth Munipalli <[email protected]> - 1.34.3
+- Fix potential tlsport selection race condition by closing socket right 
before establishing stunnel
+- Fix stunnel constantly restart issue when upgrading from 1.32.1 and before 
version to latest version
+- Speed up the way to check network availability by using systemctl is-active
+
+* Tue Nov 22 2022 Preetham Puneeth Munipalli <[email protected]> - 1.34.2
+- Fix potential issue on AL2 when watchdog trying to restart stunnel for the 
TLS mounts that existing before upgrade
+
+* Thu Sep 29 2022 Preetham Puneeth Munipalli <[email protected]> - 1.34.1
+- Update Amazon Linux 2 platform to use namespaced stunnel5
+
 * Thu Sep 1 2022 Yuan Gao <[email protected]> - 1.33.4
 - Fix potential issue where watchdog sending signal to incorrect processes.
 - Add support for enabling FIPS mode for both stunnel and AWS API calls.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/efs-utils-1.33.4/build-deb.sh 
new/efs-utils-1.34.3/build-deb.sh
--- old/efs-utils-1.33.4/build-deb.sh   2022-09-22 07:36:56.000000000 +0200
+++ new/efs-utils-1.34.3/build-deb.sh   2022-12-02 12:17:58.000000000 +0100
@@ -11,7 +11,7 @@
 
 BASE_DIR=$(pwd)
 BUILD_ROOT=${BASE_DIR}/build/debbuild
-VERSION=1.33.4
+VERSION=1.34.3
 RELEASE=1
 DEB_SYSTEM_RELEASE_PATH=/etc/os-release
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/efs-utils-1.33.4/config.ini 
new/efs-utils-1.34.3/config.ini
--- old/efs-utils-1.33.4/config.ini     2022-09-22 07:36:56.000000000 +0200
+++ new/efs-utils-1.34.3/config.ini     2022-12-02 12:17:58.000000000 +0100
@@ -7,5 +7,5 @@
 #
 
 [global]
-version=1.33.4
+version=1.34.3
 release=1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/efs-utils-1.33.4/dist/amazon-efs-utils.control 
new/efs-utils-1.34.3/dist/amazon-efs-utils.control
--- old/efs-utils-1.33.4/dist/amazon-efs-utils.control  2022-09-22 
07:36:56.000000000 +0200
+++ new/efs-utils-1.34.3/dist/amazon-efs-utils.control  2022-12-02 
12:17:58.000000000 +0100
@@ -1,6 +1,6 @@
 Package: amazon-efs-utils
 Architecture: all
-Version: 1.33.4
+Version: 1.34.3
 Section: utils
 Depends: python3, nfs-common, stunnel4 (>= 4.56), openssl (>= 1.0.2), 
util-linux
 Priority: optional
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/efs-utils-1.33.4/src/mount_efs/__init__.py 
new/efs-utils-1.34.3/src/mount_efs/__init__.py
--- old/efs-utils-1.33.4/src/mount_efs/__init__.py      2022-09-22 
07:36:56.000000000 +0200
+++ new/efs-utils-1.34.3/src/mount_efs/__init__.py      2022-12-02 
12:17:58.000000000 +0100
@@ -85,9 +85,16 @@
     BOTOCORE_PRESENT = False
 
 
-VERSION = "1.33.4"
+VERSION = "1.34.3"
 SERVICE = "elasticfilesystem"
 
+AMAZON_LINUX_2_RELEASE_ID = "Amazon Linux release 2 (Karoo)"
+AMAZON_LINUX_2_PRETTY_NAME = "Amazon Linux 2"
+AMAZON_LINUX_2_RELEASE_VERSIONS = [
+    AMAZON_LINUX_2_RELEASE_ID,
+    AMAZON_LINUX_2_PRETTY_NAME,
+]
+
 CLONE_NEWNET = 0x40000000
 CONFIG_FILE = "/etc/amazon/efs/efs-utils.conf"
 CONFIG_SECTION = "mount"
@@ -932,28 +939,25 @@
     return lower_bound, upper_bound
 
 
-def choose_tls_port(config, options):
+def choose_tls_port_and_get_bind_sock(config, options):
     if "tlsport" in options:
         ports_to_try = [int(options["tlsport"])]
     else:
         lower_bound, upper_bound = get_tls_port_range(config)
 
-        tls_ports = list(range(lower_bound, upper_bound))
-
-        # Choose a random midpoint, and then try ports in-order from there
-        mid = random.randrange(len(tls_ports))
+        ports_to_try = list(range(lower_bound, upper_bound))
 
-        ports_to_try = tls_ports[mid:] + tls_ports[:mid]
-        assert len(tls_ports) == len(ports_to_try)
+        # shuffle the ports_to_try to reduce possibility of multiple mounts 
starting from same port range
+        random.shuffle(ports_to_try)
 
     if "netns" not in options:
-        tls_port = find_tls_port_in_range(ports_to_try)
+        tls_port_sock = find_tls_port_in_range_and_get_bind_sock(ports_to_try)
     else:
         with NetNS(nspath=options["netns"]):
-            tls_port = find_tls_port_in_range(ports_to_try)
+            tls_port_sock = 
find_tls_port_in_range_and_get_bind_sock(ports_to_try)
 
-    if tls_port:
-        return tls_port
+    if tls_port_sock:
+        return tls_port_sock
 
     if "tlsport" in options:
         fatal_error(
@@ -967,14 +971,13 @@
         )
 
 
-def find_tls_port_in_range(ports_to_try):
+def find_tls_port_in_range_and_get_bind_sock(ports_to_try):
     sock = socket.socket()
     for tls_port in ports_to_try:
         try:
             logging.info("binding %s", tls_port)
             sock.bind(("localhost", tls_port))
-            sock.close()
-            return tls_port
+            return sock
         except socket.error as e:
             logging.info(e)
             continue
@@ -1095,31 +1098,32 @@
 
 
 def _stunnel_bin():
-    return find_command_path(
-        "stunnel",
-        "Please install it following the instructions at "
-        
"https://docs.aws.amazon.com/efs/latest/ug/using-amazon-efs-utils.html#upgrading-stunnel";,
-    )
+    installation_message = "Please install it following the instructions at: 
https://docs.aws.amazon.com/efs/latest/ug/using-amazon-efs-utils.html#upgrading-stunnel";
+    if get_system_release_version() in AMAZON_LINUX_2_RELEASE_VERSIONS:
+        return find_command_path("stunnel5", installation_message)
+    else:
+        return find_command_path("stunnel", installation_message)
 
 
 def find_command_path(command, install_method):
+    # If not running on macOS, use linux paths
+    if not check_if_platform_is_mac():
+        env_path = (
+            
"/sbin:/usr/sbin:/usr/local/sbin:/root/bin:/usr/local/bin:/usr/bin:/bin"
+        )
+    # Homebrew on x86 macOS uses /usr/local/bin; Homebrew on Apple Silicon 
macOS uses /opt/homebrew/bin since v3.0.0
+    # For more information, see https://brew.sh/2021/02/05/homebrew-3.0.0/
+    else:
+        env_path = "/opt/homebrew/bin:/usr/local/bin"
+    os.putenv("PATH", env_path)
+
     try:
-        # If not running on macOS, use linux paths
-        if not check_if_platform_is_mac():
-            env_path = (
-                
"/sbin:/usr/sbin:/usr/local/sbin:/root/bin:/usr/local/bin:/usr/bin:/bin"
-            )
-        # Homebrew on x86 macOS uses /usr/local/bin; Homebrew on Apple Silicon 
macOS uses /opt/homebrew/bin since v3.0.0
-        # For more information, see https://brew.sh/2021/02/05/homebrew-3.0.0/
-        else:
-            env_path = "/opt/homebrew/bin:/usr/local/bin"
-        os.putenv("PATH", env_path)
         path = subprocess.check_output(["which", command])
+        return path.strip().decode()
     except subprocess.CalledProcessError as e:
         fatal_error(
             "Failed to locate %s in %s - %s" % (command, env_path, 
install_method), e
         )
-    return path.strip().decode()
 
 
 def get_system_release_version():
@@ -1342,7 +1346,7 @@
     with open(os.devnull, "w") as devnull:
         if not check_if_platform_is_mac():
             rc = subprocess.call(
-                ["systemctl", "status", "network.target"],
+                ["systemctl", "is-active", "network.target"],
                 stdout=devnull,
                 stderr=devnull,
                 close_fds=True,
@@ -1456,6 +1460,13 @@
             raise
 
 
+# Example of a localhost bind sock: sock.bind(('localhost',12345))
+# sock.getsockname() -> ('127.0.0.1', 12345)
+# This function returns the port of the bind socket, in the example is 12345
+def get_tls_port_from_sock(tls_port_sock):
+    return tls_port_sock.getsockname()[1]
+
+
 @contextmanager
 def bootstrap_tls(
     config,
@@ -1467,85 +1478,93 @@
     state_file_dir=STATE_FILE_DIR,
     fallback_ip_address=None,
 ):
-    tls_port = choose_tls_port(config, options)
-    # override the tlsport option so that we can later override the port the 
NFS client uses to connect to stunnel.
-    # if the user has specified tlsport=X at the command line this will just 
re-set tlsport to X.
-    options["tlsport"] = tls_port
-
-    use_iam = "iam" in options
-    ap_id = options.get("accesspoint")
-    cert_details = {}
-    security_credentials = None
-    client_info = get_client_info(config)
-    region = get_target_region(config)
-
-    if use_iam:
-        aws_creds_uri = options.get("awscredsuri")
-        if aws_creds_uri:
-            kwargs = {"aws_creds_uri": aws_creds_uri}
-        else:
-            kwargs = {"awsprofile": get_aws_profile(options, use_iam)}
-
-        security_credentials, credentials_source = 
get_aws_security_credentials(
-            config, use_iam, region, **kwargs
-        )
+    tls_port_sock = choose_tls_port_and_get_bind_sock(config, options)
+    tls_port = get_tls_port_from_sock(tls_port_sock)
 
-        if credentials_source:
-            cert_details["awsCredentialsMethod"] = credentials_source
-
-    if ap_id:
-        cert_details["accessPoint"] = ap_id
-
-    # additional symbol appended to avoid naming collisions
-    cert_details["mountStateDir"] = (
-        get_mount_specific_filename(fs_id, mountpoint, tls_port) + "+"
-    )
-    # common name for certificate signing request is max 64 characters
-    cert_details["commonName"] = socket.gethostname()[0:64]
-    region = get_target_region(config)
-    cert_details["region"] = region
-    cert_details["certificateCreationTime"] = create_certificate(
-        config,
-        cert_details["mountStateDir"],
-        cert_details["commonName"],
-        cert_details["region"],
-        fs_id,
-        security_credentials,
-        ap_id,
-        client_info,
-        base_path=state_file_dir,
-    )
-    cert_details["certificate"] = os.path.join(
-        state_file_dir, cert_details["mountStateDir"], "certificate.pem"
-    )
-    cert_details["privateKey"] = get_private_key_path()
-    cert_details["fsId"] = fs_id
-
-    start_watchdog(init_system)
+    try:
+        # override the tlsport option so that we can later override the port 
the NFS client uses to connect to stunnel.
+        # if the user has specified tlsport=X at the command line this will 
just re-set tlsport to X.
+        options["tlsport"] = tls_port
+
+        use_iam = "iam" in options
+        ap_id = options.get("accesspoint")
+        cert_details = {}
+        security_credentials = None
+        client_info = get_client_info(config)
+        region = get_target_region(config)
+
+        if use_iam:
+            aws_creds_uri = options.get("awscredsuri")
+            if aws_creds_uri:
+                kwargs = {"aws_creds_uri": aws_creds_uri}
+            else:
+                kwargs = {"awsprofile": get_aws_profile(options, use_iam)}
+
+            security_credentials, credentials_source = 
get_aws_security_credentials(
+                config, use_iam, region, **kwargs
+            )
+
+            if credentials_source:
+                cert_details["awsCredentialsMethod"] = credentials_source
+
+        if ap_id:
+            cert_details["accessPoint"] = ap_id
+
+        # additional symbol appended to avoid naming collisions
+        cert_details["mountStateDir"] = (
+            get_mount_specific_filename(fs_id, mountpoint, tls_port) + "+"
+        )
+        # common name for certificate signing request is max 64 characters
+        cert_details["commonName"] = socket.gethostname()[0:64]
+        region = get_target_region(config)
+        cert_details["region"] = region
+        cert_details["certificateCreationTime"] = create_certificate(
+            config,
+            cert_details["mountStateDir"],
+            cert_details["commonName"],
+            cert_details["region"],
+            fs_id,
+            security_credentials,
+            ap_id,
+            client_info,
+            base_path=state_file_dir,
+        )
+        cert_details["certificate"] = os.path.join(
+            state_file_dir, cert_details["mountStateDir"], "certificate.pem"
+        )
+        cert_details["privateKey"] = get_private_key_path()
+        cert_details["fsId"] = fs_id
+
+        start_watchdog(init_system)
 
-    if not os.path.exists(state_file_dir):
-        create_required_directory(config, state_file_dir)
+        if not os.path.exists(state_file_dir):
+            create_required_directory(config, state_file_dir)
 
-    verify_level = int(options.get("verify", DEFAULT_STUNNEL_VERIFY_LEVEL))
-    ocsp_enabled = is_ocsp_enabled(config, options)
+        verify_level = int(options.get("verify", DEFAULT_STUNNEL_VERIFY_LEVEL))
+        ocsp_enabled = is_ocsp_enabled(config, options)
 
-    stunnel_config_file = write_stunnel_config_file(
-        config,
-        state_file_dir,
-        fs_id,
-        mountpoint,
-        tls_port,
-        dns_name,
-        verify_level,
-        ocsp_enabled,
-        options,
-        region,
-        cert_details=cert_details,
-        fallback_ip_address=fallback_ip_address,
-    )
-    tunnel_args = [_stunnel_bin(), stunnel_config_file]
-    if "netns" in options:
-        tunnel_args = ["nsenter", "--net=" + options["netns"]] + tunnel_args
+        stunnel_config_file = write_stunnel_config_file(
+            config,
+            state_file_dir,
+            fs_id,
+            mountpoint,
+            tls_port,
+            dns_name,
+            verify_level,
+            ocsp_enabled,
+            options,
+            region,
+            cert_details=cert_details,
+            fallback_ip_address=fallback_ip_address,
+        )
+        tunnel_args = [_stunnel_bin(), stunnel_config_file]
+        if "netns" in options:
+            tunnel_args = ["nsenter", "--net=" + options["netns"]] + 
tunnel_args
+    finally:
+        # Always close the socket we created when choosing TLS port only until 
now to
+        # 1. avoid concurrent TLS mount port collision 2. enable stunnel 
process to bind the port
+        logging.debug("Closing socket used to choose TLS port %s.", tls_port)
+        tls_port_sock.close()
 
     # launch the tunnel in a process group so if it has any child processes, 
they can be killed easily by the mount watchdog
     logging.info('Starting TLS tunnel: "%s"', " ".join(tunnel_args))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/efs-utils-1.33.4/src/watchdog/__init__.py 
new/efs-utils-1.34.3/src/watchdog/__init__.py
--- old/efs-utils-1.33.4/src/watchdog/__init__.py       2022-09-22 
07:36:56.000000000 +0200
+++ new/efs-utils-1.34.3/src/watchdog/__init__.py       2022-12-02 
12:17:58.000000000 +0100
@@ -15,6 +15,7 @@
 import logging
 import logging.handlers
 import os
+import platform
 import pwd
 import re
 import shutil
@@ -49,7 +50,13 @@
     from urllib2 import HTTPError, HTTPHandler, Request, URLError, 
build_opener, urlopen
 
 
-VERSION = "1.33.4"
+AMAZON_LINUX_2_RELEASE_ID = "Amazon Linux release 2 (Karoo)"
+AMAZON_LINUX_2_PRETTY_NAME = "Amazon Linux 2"
+AMAZON_LINUX_2_RELEASE_VERSIONS = [
+    AMAZON_LINUX_2_RELEASE_ID,
+    AMAZON_LINUX_2_PRETTY_NAME,
+]
+VERSION = "1.34.3"
 SERVICE = "elasticfilesystem"
 
 CONFIG_FILE = "/etc/amazon/efs/efs-utils.conf"
@@ -169,6 +176,11 @@
 # Default unmount count for consistency
 DEFAULT_UNMOUNT_COUNT_FOR_CONSISTENCY = 5
 
+MAC_OS_PLATFORM_LIST = ["darwin"]
+SYSTEM_RELEASE_PATH = "/etc/system-release"
+OS_RELEASE_PATH = "/etc/os-release"
+STUNNEL_INSTALLATION_MESSAGE = "Please install it following the instructions 
at: 
https://docs.aws.amazon.com/efs/latest/ug/using-amazon-efs-utils.html#upgrading-stunnel";
+
 
 def fatal_error(user_message, log_message=None):
     if log_message is None:
@@ -556,11 +568,7 @@
             )
 
         return resp_dict
-    except ValueError as e:
-        logging.info(
-            'ValueError parsing "%s" into json: %s. Returning response body.'
-            % (str(resp_body), e)
-        )
+    except ValueError:
         return resp_body if resp_body_type is str else 
resp_body.decode("utf-8")
 
 
@@ -817,13 +825,16 @@
         return False
 
     pid_in_stunnel_pid_file = get_pid_in_state_dir(state_file, state_file_dir)
+    # efs-utils versions older than 1.32.2 does not create a pid file in state 
dir
+    # To avoid the healthy stunnel established by those version to be treated 
as not running due to the missing pid file, which can result in stunnel being 
constantly restarted,
+    # assuming the stunnel is still running even if the stunnel pid file does 
not exist.
     if not pid_in_stunnel_pid_file:
         logging.debug(
-            "Pid file of stunnel is already removed for %s, assuming the 
stunnel with pid %s is no longer running.",
+            "Pid file of stunnel does not exist for %s. It is possible that 
the stunnel is no longer running or the mount was mounted using an older 
version efs-utils (<1.32.2). Assuming the stunnel with pid %s is still 
running.",
             state_file,
             state_pid,
         )
-        return False
+
     elif int(state_pid) != int(pid_in_stunnel_pid_file):
         logging.warning(
             "Stunnel pid mismatch in state file (pid = %s) and stunnel pid 
file (pid = %s). Assuming the "
@@ -847,18 +858,130 @@
         return False
 
 
-def start_tls_tunnel(child_procs, state_file, command):
+def check_if_platform_is_mac():
+    return sys.platform in MAC_OS_PLATFORM_LIST
+
+
+def get_system_release_version():
+    # MacOS does not maintain paths /etc/os-release and /etc/sys-release
+    if check_if_platform_is_mac():
+        return platform.platform()
+
+    try:
+        with open(SYSTEM_RELEASE_PATH) as f:
+            return f.read().strip()
+    except IOError:
+        logging.debug("Unable to read %s", SYSTEM_RELEASE_PATH)
+
+    try:
+        with open(OS_RELEASE_PATH) as f:
+            for line in f:
+                if "PRETTY_NAME" in line:
+                    return line.split("=")[1].strip()
+    except IOError:
+        logging.debug("Unable to read %s", OS_RELEASE_PATH)
+
+    return DEFAULT_UNKNOWN_VALUE
+
+
+def find_command_path(command, install_method):
+    # If not running on macOS, use linux paths
+    if not check_if_platform_is_mac():
+        env_path = (
+            
"/sbin:/usr/sbin:/usr/local/sbin:/root/bin:/usr/local/bin:/usr/bin:/bin"
+        )
+    # Homebrew on x86 macOS uses /usr/local/bin; Homebrew on Apple Silicon 
macOS uses /opt/homebrew/bin since v3.0.0
+    # For more information, see https://brew.sh/2021/02/05/homebrew-3.0.0/
+    else:
+        env_path = "/opt/homebrew/bin:/usr/local/bin"
+    os.putenv("PATH", env_path)
+
+    try:
+        path = subprocess.check_output(["which", command])
+        return path.strip().decode()
+    except subprocess.CalledProcessError as e:
+        fatal_error(
+            "Failed to locate %s in %s - %s" % (command, env_path, 
install_method), e
+        )
+
+
+# In ECS amazon linux 2, we start stunnel using `nsenter` which will run as a 
subprocess of bash, utilizes the `setns`
+# system call to join an existing namespace and then executes the specified 
program using `exec`. Any exception won't
+# be caught properly by subprocess.
+# As a precaution on ECS AL2 that stunnel bin is removed after installing new 
efs-utils, and watchdog cannot launch
+# stunnel for previous old mount, we do a replacement of stunnel path in the 
command to the stunnel5 path.
+#
+def update_stunnel_command_for_ecs_amazon_linux_2(
+    command, state, state_file_dir, state_file
+):
+    if (
+        "nsenter" in command
+        and "stunnel5" not in " ".join(command)
+        and get_system_release_version() in AMAZON_LINUX_2_RELEASE_VERSIONS
+    ):
+        for i in range(len(command)):
+            if "stunnel" in command[i] and "stunnel-config" not in command[i]:
+                command[i] = find_command_path("stunnel5", 
STUNNEL_INSTALLATION_MESSAGE)
+                break
+        logging.info(
+            "Rewriting %s with new stunnel cmd: %s for ECS Amazon Linux 2 
platform.",
+            state_file,
+            " ".join(state["cmd"]),
+        )
+        rewrite_state_file(state, state_file_dir, state_file)
+    return command
+
+
+def start_tls_tunnel(child_procs, state, state_file_dir, state_file):
     # launch the tunnel in a process group so if it has any child processes, 
they can be killed easily
+    command = state["cmd"]
     logging.info('Starting TLS tunnel: "%s"', " ".join(command))
-    tunnel = subprocess.Popen(
-        command,
-        stdout=subprocess.DEVNULL,
-        stderr=subprocess.DEVNULL,
-        preexec_fn=os.setsid,
-        close_fds=True,
+
+    command = update_stunnel_command_for_ecs_amazon_linux_2(
+        command, state, state_file_dir, state_file
     )
+    tunnel = None
+    try:
+        tunnel = subprocess.Popen(
+            command,
+            stdout=subprocess.DEVNULL,
+            stderr=subprocess.DEVNULL,
+            preexec_fn=os.setsid,
+            close_fds=True,
+        )
+    except FileNotFoundError as e:
+        logging.warning("Watchdog failed to start stunnel due to %s", e)
+
+        # https://github.com/kubernetes-sigs/aws-efs-csi-driver/issues/812 It 
is possible that the stunnel is not
+        # present anymore and replaced by stunnel5 on AL2, meanwhile watchdog 
is attempting to restart stunnel for
+        # mount using old efs-utils based on old state file generated during 
previous mount, which has stale command
+        # using stunnel bin. Update the state file if the stunnel does not 
exist anymore, and use stunnel5 on Al2.
+        #
+        if get_system_release_version() in AMAZON_LINUX_2_RELEASE_VERSIONS:
+            for i in range(len(command)):
+                if "stunnel" in command[i] and "stunnel-config" not in 
command[i]:
+                    command[i] = find_command_path(
+                        "stunnel5", STUNNEL_INSTALLATION_MESSAGE
+                    )
+                    break
+
+            tunnel = subprocess.Popen(
+                command,
+                stdout=subprocess.DEVNULL,
+                stderr=subprocess.DEVNULL,
+                preexec_fn=os.setsid,
+                close_fds=True,
+            )
+
+            state["cmd"] = command
+            logging.info(
+                "Rewriting %s with new stunnel cmd: %s for Amazon Linux 2 
platform.",
+                state_file,
+                " ".join(state["cmd"]),
+            )
+            rewrite_state_file(state, state_file_dir, state_file)
 
-    if not is_pid_running(tunnel.pid):
+    if tunnel is None or not is_pid_running(tunnel.pid):
         fatal_error(
             "Failed to initialize TLS tunnel for %s" % state_file,
             "Failed to start TLS tunnel.",
@@ -940,7 +1063,7 @@
         )
         return
 
-    new_tunnel_pid = start_tls_tunnel(child_procs, state_file, state["cmd"])
+    new_tunnel_pid = start_tls_tunnel(child_procs, state, state_file_dir, 
state_file)
     state["pid"] = new_tunnel_pid
 
     logging.debug("Rewriting %s with new pid: %d", state_file, new_tunnel_pid)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/efs-utils-1.33.4/test/mount_efs_test/test_bootstrap_tls.py 
new/efs-utils-1.34.3/test/mount_efs_test/test_bootstrap_tls.py
--- old/efs-utils-1.33.4/test/mount_efs_test/test_bootstrap_tls.py      
2022-09-22 07:36:56.000000000 +0200
+++ new/efs-utils-1.34.3/test/mount_efs_test/test_bootstrap_tls.py      
2022-12-02 12:17:58.000000000 +0100
@@ -17,6 +17,7 @@
 MOUNT_POINT = "/mnt"
 REGION = "us-east-1"
 
+
 DEFAULT_TLS_PORT = 20049
 
 EXPECTED_STUNNEL_CONFIG_FILE_BASE = "stunnel-config.fs-deadbeef.mnt."
@@ -171,6 +172,11 @@
     state_file_dir = str(tmpdir)
 
     tls_port = 1000
+    tls_port_sock_mock = MagicMock()
+    tls_port_sock_mock.getsockname.return_value = ("local_host", tls_port)
+    tls_port_sock_mock.close.side_effect = None
+    mocker.patch("socket.socket", return_value=tls_port_sock_mock)
+
     mocker.patch("mount_efs._stunnel_bin", return_value="/usr/bin/stunnel")
     with mount_efs.bootstrap_tls(
         MOCK_CONFIG,
@@ -189,7 +195,11 @@
 
     assert "/usr/bin/stunnel" in popen_args
     assert EXPECTED_STUNNEL_CONFIG_FILE in popen_args
-    assert 1000 == write_config_args[4]  # positional argument for tls_port
+    assert tls_port == write_config_args[4]  # positional argument for tls_port
+    # Ensure tls port socket is closed in bootstrap_tls
+    # The number is two here, the first one is the actual socket when choosing 
tls port, the second one is a socket to
+    # verify tls port can be connected after establishing TLS stunnel. They 
share the same mock.
+    assert 2 == tls_port_sock_mock.close.call_count
 
 
 def test_bootstrap_tls_non_default_verify_level(mocker, tmpdir):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/efs-utils-1.33.4/test/mount_efs_test/test_choose_tls_port.py 
new/efs-utils-1.34.3/test/mount_efs_test/test_choose_tls_port.py
--- old/efs-utils-1.33.4/test/mount_efs_test/test_choose_tls_port.py    
2022-09-22 07:36:56.000000000 +0200
+++ new/efs-utils-1.34.3/test/mount_efs_test/test_choose_tls_port.py    
2022-12-02 12:17:58.000000000 +0100
@@ -4,6 +4,7 @@
 # for the specific language governing permissions and limitations under
 # the License.
 
+import random
 import socket
 from unittest.mock import MagicMock
 
@@ -19,7 +20,10 @@
     from configparser import ConfigParser
 
 DEFAULT_TLS_PORT_RANGE_LOW = 20049
-DEFAULT_TLS_PORT_RANGE_HIGH = 20449
+DEFAULT_TLS_PORT_RANGE_HIGH = 21049
+DEFAULT_TLS_PORT = random.randrange(
+    DEFAULT_TLS_PORT_RANGE_LOW, DEFAULT_TLS_PORT_RANGE_HIGH
+)
 
 
 def _get_config():
@@ -42,25 +46,30 @@
 
 
 def test_choose_tls_port_first_try(mocker):
-    mocker.patch("socket.socket", return_value=MagicMock())
+    sock_mock = MagicMock()
+    sock_mock.getsockname.return_value = ("local_host", DEFAULT_TLS_PORT)
+    mocker.patch("socket.socket", return_value=sock_mock)
     options = {}
 
-    tls_port = mount_efs.choose_tls_port(_get_config(), options)
-
+    tls_port_sock = mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), 
options)
+    tls_port = mount_efs.get_tls_port_from_sock(tls_port_sock)
     assert DEFAULT_TLS_PORT_RANGE_LOW <= tls_port <= 
DEFAULT_TLS_PORT_RANGE_HIGH
 
 
 def test_choose_tls_port_second_try(mocker):
     bad_sock = MagicMock()
     bad_sock.bind.side_effect = [socket.error, None]
+    bad_sock.getsockname.return_value = ("local_host", DEFAULT_TLS_PORT)
     options = {}
 
     mocker.patch("socket.socket", return_value=bad_sock)
 
-    tls_port = mount_efs.choose_tls_port(_get_config(), options)
+    tls_port_sock = mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), 
options)
+    tls_port = mount_efs.get_tls_port_from_sock(tls_port_sock)
 
     assert DEFAULT_TLS_PORT_RANGE_LOW <= tls_port <= 
DEFAULT_TLS_PORT_RANGE_HIGH
     assert 2 == bad_sock.bind.call_count
+    assert 1 == bad_sock.getsockname.call_count
 
 
 def test_choose_tls_port_never_succeeds(mocker, capsys):
@@ -71,7 +80,7 @@
     mocker.patch("socket.socket", return_value=bad_sock)
 
     with pytest.raises(SystemExit) as ex:
-        mount_efs.choose_tls_port(_get_config(), options)
+        mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), options)
 
     assert 0 != ex.value.code
 
@@ -85,12 +94,15 @@
 
 
 def test_choose_tls_port_option_specified(mocker):
-    mocker.patch("socket.socket", return_value=MagicMock())
-    options = {"tlsport": 1000}
+    sock_mock = MagicMock()
+    sock_mock.getsockname.return_value = ("local_host", DEFAULT_TLS_PORT)
+    mocker.patch("socket.socket", return_value=sock_mock)
+    options = {"tlsport": DEFAULT_TLS_PORT}
 
-    tls_port = mount_efs.choose_tls_port(_get_config(), options)
+    tls_port_sock = mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), 
options)
+    tls_port = mount_efs.get_tls_port_from_sock(tls_port_sock)
 
-    assert 1000 == tls_port
+    assert DEFAULT_TLS_PORT == tls_port
 
 
 def test_choose_tls_port_option_specified_unavailable(mocker, capsys):
@@ -101,7 +113,7 @@
     mocker.patch("socket.socket", return_value=bad_sock)
 
     with pytest.raises(SystemExit) as ex:
-        mount_efs.choose_tls_port(_get_config(), options)
+        mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), options)
 
     assert 0 != ex.value.code
 
@@ -117,7 +129,7 @@
     mocker.patch("socket.socket", return_value=MagicMock())
     options = {"netns": "/proc/1000/ns/net"}
 
-    mount_efs.choose_tls_port(_get_config(), options)
+    mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), options)
     utils.assert_called(setns_mock)
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/efs-utils-1.33.4/test/mount_efs_test/test_helper_function.py 
new/efs-utils-1.34.3/test/mount_efs_test/test_helper_function.py
--- old/efs-utils-1.33.4/test/mount_efs_test/test_helper_function.py    
2022-09-22 07:36:56.000000000 +0200
+++ new/efs-utils-1.34.3/test/mount_efs_test/test_helper_function.py    
2022-12-02 12:17:58.000000000 +0100
@@ -5,8 +5,10 @@
 # the License.
 
 import logging
+import sys
+import unittest
 from collections import namedtuple
-from unittest.mock import MagicMock
+from unittest.mock import MagicMock, mock_open
 
 import pytest
 from botocore.exceptions import ProfileNotFound
@@ -25,11 +27,13 @@
 except ImportError:
     from urllib.error import HTTPError, URLError
 
-
 DEFAULT_REGION = "us-east-1"
 ACCESS_KEY_ID_VAL = "FAKE_AWS_ACCESS_KEY_ID"
 SECRET_ACCESS_KEY_VAL = "FAKE_AWS_SECRET_ACCESS_KEY"
 SESSION_TOKEN_VAL = "FAKE_SESSION_TOKEN"
+MACOS = "macOS"
+AL2 = "Amazon Linux release 2"
+NON_AL2_RELEASE_ID_VAL = "FAKE_NON_AL2_RELEASE_ID_VAL"
 
 
 def get_config(
@@ -459,3 +463,78 @@
         "profile", "test_profile"
     )
     boto_session_mock.get_credentials.assert_called_once_with()
+
+
+def test_get_system_release_version_macos(mocker):
+    mocker.patch("mount_efs.check_if_platform_is_mac", return_value=True)
+    platform_mock = mocker.patch("platform.platform", return_value=MACOS)
+    assert MACOS == mount_efs.get_system_release_version()
+    utils.assert_called_once(platform_mock)
+
+
+def test_get_system_release_version_linux_read_from_sys_release_path(mocker):
+    mocker.patch("mount_efs.check_if_platform_is_mac", return_value=False)
+    open_mock = mocker.patch("builtins.open", mock_open(read_data=AL2))
+    platform_mock = mocker.patch("platform.platform")
+    assert AL2 == mount_efs.get_system_release_version()
+    utils.assert_not_called(platform_mock)
+    utils.assert_called_once(open_mock)
+
+
[email protected](sys.version_info[1] < 7, "Not supported in python3.6 and 
below.")
+def test_get_system_release_version_linux_read_from_os_release_path(mocker):
+    mocker.patch("mount_efs.check_if_platform_is_mac", return_value=False)
+    mock = mock_open()
+    mock.side_effect = [
+        FileNotFoundError,
+        mock_open(read_data="PRETTY_NAME=Amazon Linux release 2").return_value,
+    ]
+    open_mock = mocker.patch("builtins.open", mock)
+    platform_mock = mocker.patch("platform.platform")
+    assert AL2 == mount_efs.get_system_release_version()
+    utils.assert_not_called(platform_mock)
+    utils.assert_called_n_times(open_mock, 2)
+
+
+def test_get_system_release_version_linux_unknown(mocker):
+    mocker.patch("mount_efs.check_if_platform_is_mac", return_value=False)
+    open_mock = mocker.patch("builtins.open", side_effect=FileNotFoundError)
+    platform_mock = mocker.patch("platform.platform")
+    assert mount_efs.DEFAULT_UNKNOWN_VALUE == 
mount_efs.get_system_release_version()
+    utils.assert_not_called(platform_mock)
+    utils.assert_called_n_times(open_mock, 2)
+
+
+def test_stunnel5_al2_with_pretty_name(mocker):
+    check_output_mock = mocker.patch("subprocess.check_output")
+    mocker.patch(
+        "mount_efs.get_system_release_version",
+        return_value=mount_efs.AMAZON_LINUX_2_PRETTY_NAME,
+    )
+    mount_efs._stunnel_bin()
+    args, _ = check_output_mock.call_args
+    args = args[0]
+    assert "stunnel5" == args[1]
+
+
+def test_stunnel5_al2_with_release_id(mocker):
+    check_output_mock = mocker.patch("subprocess.check_output")
+    mocker.patch(
+        "mount_efs.get_system_release_version",
+        return_value=mount_efs.AMAZON_LINUX_2_RELEASE_ID,
+    )
+    mount_efs._stunnel_bin()
+    args, _ = check_output_mock.call_args
+    args = args[0]
+    assert "stunnel5" == args[1]
+
+
+def test_stunnel5_non_al2(mocker):
+    check_output_mock = mocker.patch("subprocess.check_output")
+    mocker.patch(
+        "mount_efs.get_system_release_version", 
return_value=NON_AL2_RELEASE_ID_VAL
+    )
+    mount_efs._stunnel_bin()
+    args, _ = check_output_mock.call_args
+    args = args[0]
+    assert "stunnel" == args[1]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/efs-utils-1.33.4/test/watchdog_test/test_helper_function.py 
new/efs-utils-1.34.3/test/watchdog_test/test_helper_function.py
--- old/efs-utils-1.33.4/test/watchdog_test/test_helper_function.py     
2022-09-22 07:36:56.000000000 +0200
+++ new/efs-utils-1.34.3/test/watchdog_test/test_helper_function.py     
2022-12-02 12:17:58.000000000 +0100
@@ -5,8 +5,10 @@
 # the License.
 
 import logging
+import sys
+import unittest
 from collections import namedtuple
-from unittest.mock import MagicMock
+from unittest.mock import MagicMock, mock_open
 
 from botocore.exceptions import ProfileNotFound
 
@@ -30,6 +32,8 @@
 ACCESS_KEY_ID_VAL = "FAKE_AWS_ACCESS_KEY_ID"
 SECRET_ACCESS_KEY_VAL = "FAKE_AWS_SECRET_ACCESS_KEY"
 SESSION_TOKEN_VAL = "FAKE_SESSION_TOKEN"
+MACOS = "macOS"
+AL2 = "Amazon Linux release 2"
 
 
 def get_config(
@@ -397,3 +401,43 @@
         "-482e-b8b9-0e5e6887e411/mount"
         == watchdog.get_mountpoint_from_nfs_mounts(state_file_name, nfs_mounts)
     )
+
+
+def test_get_system_release_version_macos(mocker):
+    mocker.patch("watchdog.check_if_platform_is_mac", return_value=True)
+    platform_mock = mocker.patch("platform.platform", return_value=MACOS)
+    assert MACOS == watchdog.get_system_release_version()
+    utils.assert_called_once(platform_mock)
+
+
+def test_get_system_release_version_linux_read_from_sys_release_path(mocker):
+    mocker.patch("watchdog.check_if_platform_is_mac", return_value=False)
+    open_mock = mocker.patch("builtins.open", mock_open(read_data=AL2))
+    platform_mock = mocker.patch("platform.platform")
+    assert AL2 == watchdog.get_system_release_version()
+    utils.assert_not_called(platform_mock)
+    utils.assert_called_once(open_mock)
+
+
[email protected](sys.version_info[1] < 7, "Not supported in python3.6 and 
below.")
+def test_get_system_release_version_linux_read_from_os_release_path(mocker):
+    mocker.patch("watchdog.check_if_platform_is_mac", return_value=False)
+    mock = mock_open()
+    mock.side_effect = [
+        FileNotFoundError,
+        mock_open(read_data="PRETTY_NAME=Amazon Linux release 2").return_value,
+    ]
+    open_mock = mocker.patch("builtins.open", mock)
+    platform_mock = mocker.patch("platform.platform")
+    assert AL2 == watchdog.get_system_release_version()
+    utils.assert_not_called(platform_mock)
+    utils.assert_called_n_times(open_mock, 2)
+
+
+def test_get_system_release_version_linux_unknown(mocker):
+    mocker.patch("watchdog.check_if_platform_is_mac", return_value=False)
+    open_mock = mocker.patch("builtins.open", side_effect=FileNotFoundError)
+    platform_mock = mocker.patch("platform.platform")
+    assert watchdog.DEFAULT_UNKNOWN_VALUE == 
watchdog.get_system_release_version()
+    utils.assert_not_called(platform_mock)
+    utils.assert_called_n_times(open_mock, 2)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/efs-utils-1.33.4/test/watchdog_test/test_send_signal_to_stunnel_processes.py
 
new/efs-utils-1.34.3/test/watchdog_test/test_send_signal_to_stunnel_processes.py
--- 
old/efs-utils-1.33.4/test/watchdog_test/test_send_signal_to_stunnel_processes.py
    2022-09-22 07:36:56.000000000 +0200
+++ 
new/efs-utils-1.34.3/test/watchdog_test/test_send_signal_to_stunnel_processes.py
    2022-12-02 12:17:58.000000000 +0100
@@ -114,10 +114,12 @@
     assert not os.path.exists(os.path.join(str(mount_dir), 
watchdog.STUNNEL_PID_FILE))
     mock_log_debug = mocker.patch("logging.debug")
 
-    assert False == watchdog.is_mount_stunnel_proc_running(PID, STATE_FILE, 
str(tmpdir))
+    assert True == watchdog.is_mount_stunnel_proc_running(PID, STATE_FILE, 
str(tmpdir))
 
-    debug_log = mock_log_debug.call_args[0][0]
-    assert "Pid file of stunnel is already removed" in debug_log
+    assert "Pid file of stunnel does not exist" in str(
+        mock_log_debug.call_args_list[0][0]
+    )
+    assert "is running with pid " in str(mock_log_debug.call_args_list[1][0])
 
 
 def test_is_mount_stunnel_proc_running_pid_mismatch(mocker, tmpdir):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/efs-utils-1.33.4/test/watchdog_test/test_start_tls_tunnel.py 
new/efs-utils-1.34.3/test/watchdog_test/test_start_tls_tunnel.py
--- old/efs-utils-1.33.4/test/watchdog_test/test_start_tls_tunnel.py    
2022-09-22 07:36:56.000000000 +0200
+++ new/efs-utils-1.34.3/test/watchdog_test/test_start_tls_tunnel.py    
2022-12-02 12:17:58.000000000 +0100
@@ -4,50 +4,158 @@
 # for the specific language governing permissions and limitations under
 # the License.
 
+import json
+import os
+import tempfile
+import unittest
 from unittest.mock import MagicMock
 
 import pytest
 
 import watchdog
 
+from .. import utils
+
 PID = 1234
 
 
-def _mock_popen(mocker, returncode=0):
+def _get_popen_mock(pid=PID):
     popen_mock = MagicMock()
-    popen_mock.communicate.return_value = (
-        "stdout",
-        "stderr",
-    )
-    popen_mock.pid = PID
-    popen_mock.returncode = returncode
+    popen_mock.pid = pid
+    return popen_mock
+
+
+def _mock_popen(mocker):
+    return mocker.patch("subprocess.Popen", return_value=_get_popen_mock())
+
 
-    return mocker.patch("subprocess.Popen", return_value=popen_mock)
+def _initiate_state_file(tmpdir, cmd=None):
+    state = {
+        "pid": PID - 1,
+        "cmd": cmd
+        if cmd
+        else [
+            "/usr/bin/stunnel",
+            "/var/run/efs/stunnel-config.fs-deadbeef.mnt.21007",
+        ],
+    }
+    state_file = tempfile.mkstemp(prefix="state", dir=str(tmpdir))[1]
+    with open(state_file, "w") as f:
+        f.write(json.dumps(state))
+    return state, state_file
 
 
-def test_start_tls_tunnel(mocker):
+def test_start_tls_tunnel(mocker, tmpdir):
     _mock_popen(mocker)
     mocker.patch("watchdog.is_pid_running", return_value=True)
 
+    state, state_file = _initiate_state_file(tmpdir)
     procs = []
-    pid = watchdog.start_tls_tunnel(procs, "fs-deadbeef", "stunnel")
+    pid = watchdog.start_tls_tunnel(procs, state, str(tmpdir), state_file)
 
     assert PID == pid
     assert 1 == len(procs)
 
 
-def test_start_tls_tunnel_fails(mocker, capsys):
+def test_start_tls_tunnel_fails(mocker, capsys, tmpdir):
     _mock_popen(mocker)
     mocker.patch("watchdog.is_pid_running", return_value=False)
 
+    state, state_file = _initiate_state_file(tmpdir)
     procs = []
-
     with pytest.raises(SystemExit) as ex:
-        watchdog.start_tls_tunnel(procs, "fs-deadbeef", "stunnel")
+        watchdog.start_tls_tunnel(procs, state, str(tmpdir), state_file)
 
     assert 0 == len(procs)
-
     assert 0 != ex.value.code
 
     out, err = capsys.readouterr()
     assert "Failed to initialize TLS tunnel" in err
+
+
+# https://github.com/kubernetes-sigs/aws-efs-csi-driver/issues/812 The 
watchdog is trying to launch stunnel on AL2 for
+# mounts using older version of efs-utils based on old state file command, 
while somehow the stunnel bin is removed
+# after updating driver with new efs-utils(using stunnel5 bin). Watchdog 
should handle the case when the stunnel cannot
+# be found, and fallback to use stunnel5 on AL2.
+#
+def 
_test_start_tls_tunnel_for_mount_via_older_version_of_efs_utils_on_amazon_linux_2_helper(
+    mocker, tmpdir, release_version
+):
+    popen_mocker = mocker.patch(
+        "subprocess.Popen", side_effect=[FileNotFoundError, _get_popen_mock()]
+    )
+    mocker.patch("watchdog.is_pid_running", return_value=True)
+    mocker.patch(
+        "watchdog.get_system_release_version",
+        return_value=release_version,
+    )
+    mocker.patch("watchdog.find_command_path", 
return_value="/usr/sbin/stunnel5")
+
+    state, state_file = _initiate_state_file(tmpdir)
+    procs = []
+    pid = watchdog.start_tls_tunnel(
+        procs, state, str(tmpdir), state_file.split("/")[-1]
+    )
+    assert PID == pid
+    assert 1 == len(procs)
+    utils.assert_called_n_times(popen_mocker, 2)
+
+    with open(state_file) as f:
+        state = json.load(f)
+
+    assert "/usr/sbin/stunnel5" == state["cmd"][0]
+
+
+def 
test_start_tls_tunnel_for_mount_via_older_version_of_efs_utils_on_amazon_linux_2_with_release_id(
+    mocker, tmpdir
+):
+    
_test_start_tls_tunnel_for_mount_via_older_version_of_efs_utils_on_amazon_linux_2_helper(
+        mocker, tmpdir, watchdog.AMAZON_LINUX_2_RELEASE_ID
+    )
+
+
+def 
test_start_tls_tunnel_for_mount_via_older_version_of_efs_utils_on_amazon_linux_2_with_pretty_name(
+    mocker, tmpdir
+):
+    
_test_start_tls_tunnel_for_mount_via_older_version_of_efs_utils_on_amazon_linux_2_helper(
+        mocker, tmpdir, watchdog.AMAZON_LINUX_2_PRETTY_NAME
+    )
+
+
+# On ECS AL2, the stunnel is started in the given network namespace, i.e. the 
command to start stunnel is different.
+# e.g. nsenter --net=/proc/1234/ns/net /usr/bin/stunnel 
/var/run/efs/stunnel-config.fs-deadbeef.12345
+# Need to make sure after we detect the stunnel is not found, we update the 
old mount to use stunnel5, and command is
+# nsenter --net=/proc/1234/ns/net /usr/bin/stunnel5 
/var/run/efs/stunnel-config.fs-deadbeef.12345
+#
+def 
test_start_tls_tunnel_for_mount_via_older_version_of_efs_utils_on_ecs_amazon_linux_2(
+    mocker, tmpdir
+):
+    _mock_popen(mocker)
+    mocker.patch("watchdog.is_pid_running", return_value=True)
+    mocker.patch(
+        "watchdog.get_system_release_version",
+        return_value=watchdog.AMAZON_LINUX_2_RELEASE_ID,
+    )
+    mocker.patch("watchdog.find_command_path", 
return_value="/usr/sbin/stunnel5")
+
+    namespace = "--net=/proc/1234/ns/net"
+    cmd = [
+        "nsenter",
+        namespace,
+        "/usr/bin/stunnel",
+        "/var/run/efs/stunnel-config.fs-deadbeef.mnt.21007",
+    ]
+    state, state_file = _initiate_state_file(tmpdir, cmd=cmd)
+    procs = []
+    pid = watchdog.start_tls_tunnel(
+        procs, state, str(tmpdir), state_file.split("/")[-1]
+    )
+    assert PID == pid
+    assert 1 == len(procs)
+
+    with open(state_file) as f:
+        state = json.load(f)
+
+    assert " ".join(["nsenter", namespace, "/usr/sbin/stunnel5"]) in " ".join(
+        state["cmd"]
+    )

Reply via email to