11import glob
2- import logging
32import os
43import re
54import subprocess
65import uuid
76from typing import Dict , List , Optional , Tuple
87
98from tests import test_logger
9+ from tests .constants import (
10+ DEFAULT_HELM_CHART_PATH_ENV_VAR_NAME ,
11+ OCI_HELM_REGION_ENV_VAR_NAME ,
12+ OCI_HELM_REGISTRY_ENV_VAR_NAME ,
13+ OCI_HELM_VERSION_ENV_VAR_NAME ,
14+ )
1015
1116logger = test_logger .get_test_logger (__name__ )
1217
18+ # LOCAL_CRDS_DIR is the dir where local helm chart's CRDs are copied in tests image
19+ LOCAL_CRDS_DIR = "helm_chart/crds"
20+ OCI_HELM_REGISTRY_ECR = "268558157000.dkr.ecr.us-east-1.amazonaws.com"
21+
1322
1423def helm_template (
1524 helm_args : Dict ,
@@ -25,7 +34,7 @@ def helm_template(
2534 command_args .append ("--show-only" )
2635 command_args .append (templates )
2736
28- args = ("helm" , "template" , * ( command_args ) , helm_chart_path )
37+ args = ("helm" , "template" , * command_args , helm_chart_path )
2938 logger .info (" " .join (args ))
3039
3140 yaml_file_name = "{}.yaml" .format (str (uuid .uuid4 ()))
@@ -145,6 +154,55 @@ def process_run_and_check(args, **kwargs):
145154 raise
146155
147156
157+ def helm_registry_login_to_ecr (helm_registry : str , region : str ):
158+ logger .info (f"Attempting to log into ECR registry: { helm_registry } , using helm registry login." )
159+
160+ aws_command = ["aws" , "ecr" , "get-login-password" , "--region" , region ]
161+
162+ # as we can see the password is being provided by stdin, that would mean we will have to
163+ # pipe the aws_command (it figures out the password) into helm_command.
164+ helm_command = ["helm" , "registry" , "login" , "--username" , "AWS" , "--password-stdin" , helm_registry ]
165+
166+ try :
167+ logger .info ("Starting AWS ECR credential retrieval." )
168+ aws_proc = subprocess .Popen (
169+ aws_command , stdout = subprocess .PIPE , stderr = subprocess .PIPE , text = True # Treat input/output as text strings
170+ )
171+
172+ logger .info ("Starting Helm registry login." )
173+ helm_proc = subprocess .Popen (
174+ helm_command , stdin = aws_proc .stdout , stdout = subprocess .PIPE , stderr = subprocess .PIPE , text = True
175+ )
176+
177+ # Close the stdout stream of aws_proc in the parent process
178+ # to prevent resource leakage (only needed if you plan to do more processing)
179+ aws_proc .stdout .close ()
180+
181+ # Wait for the Helm command (helm_proc) to finish and capture its output
182+ helm_stdout , helm_stderr = helm_proc .communicate ()
183+
184+ # Wait for the AWS process to finish as well
185+ aws_proc .wait ()
186+
187+ if aws_proc .returncode != 0 :
188+ _ , aws_stderr = aws_proc .communicate ()
189+ raise Exception (f"aws command to get password failed. Error: { aws_stderr } " )
190+
191+ if helm_proc .returncode == 0 :
192+ logger .info ("Login to helm registry was successful." )
193+ logger .info (helm_stdout .strip ())
194+ else :
195+ raise Exception (
196+ f"Login to helm registry failed, Exit code: { helm_proc .returncode } , Error: { helm_stderr .strip ()} "
197+ )
198+
199+ except FileNotFoundError as e :
200+ # This catches errors if 'aws' or 'helm' are not in the PATH
201+ raise Exception (f"Command not found. Please ensure '{ e .filename } ' is installed and in your system's PATH." )
202+ except Exception as e :
203+ raise Exception (f"An unexpected error occurred: { e } ." )
204+
205+
148206def helm_upgrade (
149207 name : str ,
150208 namespace : str ,
@@ -162,7 +220,7 @@ def helm_upgrade(
162220 chart_dir = helm_chart_path
163221
164222 if apply_crds_first :
165- apply_crds_from_chart (chart_dir )
223+ apply_crds_from_chart (LOCAL_CRDS_DIR )
166224
167225 command_args = _create_helm_args (helm_args , helm_options )
168226 args = [
@@ -183,11 +241,11 @@ def helm_upgrade(
183241 process_run_and_check (command , check = True , capture_output = True , shell = True )
184242
185243
186- def apply_crds_from_chart (chart_dir : str ):
187- crd_files = glob .glob (os .path .join (chart_dir , "crds" , "*.yaml" ))
244+ def apply_crds_from_chart (crds_dir : str ):
245+ crd_files = glob .glob (os .path .join (crds_dir , "*.yaml" ))
188246
189247 if not crd_files :
190- raise Exception (f"No CRD files found in chart directory: { chart_dir } " )
248+ raise Exception (f"No CRD files found in chart directory: { crds_dir } " )
191249
192250 logger .info (f"Found { len (crd_files )} CRD files to apply:" )
193251
@@ -230,3 +288,29 @@ def _create_helm_args(helm_args: Dict[str, str], helm_options: Optional[List[str
230288 command_args .extend (helm_options )
231289
232290 return command_args
291+
292+
293+ # helm_chart_path_and_version returns the chart path and version that we would like to install to run the E2E tests.
294+ # for local tests it returns early with local helm chart dir and for other scenarios it figures out the chart and version
295+ # based on the caller. In most of the cases we will install chart from OCI registry but for the tests where we would like
296+ # to install MEKO's specific version or MCK's specific version, we would expect `helm_chart_path` to set already.
297+ def helm_chart_path_and_version (helm_chart_path : str , operator_version : str ) -> tuple [str , str ]:
298+ # if helm_chart_path is not passed, use the default value from DEFAULT_HELM_CHART_PATH
299+ if not helm_chart_path :
300+ helm_chart_path = os .getenv (DEFAULT_HELM_CHART_PATH_ENV_VAR_NAME )
301+
302+ if helm_chart_path .startswith ("oci://" ):
303+ # If operator_version is not passed, we want to install the current version.
304+ if not operator_version :
305+ operator_version = os .environ .get (OCI_HELM_VERSION_ENV_VAR_NAME )
306+
307+ registry = os .environ .get (OCI_HELM_REGISTRY_ENV_VAR_NAME )
308+ # If ECR we need to login first to the OCI container registry
309+ if registry == OCI_HELM_REGISTRY_ECR :
310+ region = os .environ .get (OCI_HELM_REGION_ENV_VAR_NAME )
311+ try :
312+ helm_registry_login_to_ecr (registry , region )
313+ except Exception as e :
314+ raise Exception (f"Failed to login to ECR helm registry { registry } . Error: { e } " )
315+
316+ return helm_chart_path , operator_version
0 commit comments