From dfbc534fb6c805f67d3766e560646cc5d7278692 Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Wed, 8 Oct 2025 16:10:57 +0200 Subject: [PATCH 01/26] Publish helm chart to OCI registry for PR patches --- scripts/dev/helm_registry_login.sh | 39 +++++++++++++++ scripts/publish_helm_chart.py | 78 ++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100755 scripts/dev/helm_registry_login.sh create mode 100644 scripts/publish_helm_chart.py diff --git a/scripts/dev/helm_registry_login.sh b/scripts/dev/helm_registry_login.sh new file mode 100755 index 000000000..1d3ca2e3f --- /dev/null +++ b/scripts/dev/helm_registry_login.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +ECR_REGISTRY="268558157000.dkr.ecr.us-east-1.amazonaws.com" +AWS_REGION="us-east-1" + +source scripts/dev/set_env_context.sh + +export PATH=${PROJECT_DIR}/bin:$PATH + +echo "Checking if helm CLI is installed..." +if ! command -v helm &> /dev/null +then + echo "Error: helm CLI could not be found." + echo "Please ensure helm is installed and in your system's PATH." + exit 1 +fi + +echo "Checking if aws CLI is installed..." +if ! command -v aws &> /dev/null +then + echo "Error: aws CLI could not be found." + echo "Please ensure aws CLI is installed and configured." + exit 1 +fi + +echo "Logging into OCI Registry: ${ECR_REGISTRY} in region ${AWS_REGION}..." + +if aws ecr get-login-password --region "$AWS_REGION" | helm registry login \ + --username AWS \ + --password-stdin \ + "$ECR_REGISTRY" +then + echo "Helm successfully logged into the OCI registry." + exit 0 +else + echo "ERROR: Helm login to ECR registry failed." + echo "Please ensure your AWS credentials have permission to access ECR in the specified region." + exit 1 +fi diff --git a/scripts/publish_helm_chart.py b/scripts/publish_helm_chart.py new file mode 100644 index 000000000..7b7eb0a9c --- /dev/null +++ b/scripts/publish_helm_chart.py @@ -0,0 +1,78 @@ +import subprocess +import os +import yaml + +from lib.base_logger import logger + +CHART_DIR = "helm_chart" + +OCI_REGISTRY = "oci://268558157000.dkr.ecr.us-east-1.amazonaws.com/dev/helm-charts" + +def run_command(command: list[str], description: str): + try: + subprocess.run(command, check=True, text=True, capture_output=False) + logger.info(f"Command {' '.join(command)} executed successfully.") + except subprocess.CalledProcessError as e: + logger.error(f"Error executing command: {' '.join(command)}") + raise RuntimeError(f"{description} failed.") from e + except FileNotFoundError: + raise FileNotFoundError("Error: 'helm' command not found. Ensure Helm CLI is installed and in your PATH.") + +def update_chart_and_get_metadata(chart_dir: str) -> tuple[str, str]: + chart_path = os.path.join(chart_dir, "Chart.yaml") + version_id = os.environ.get('version_id') + if not version_id: + raise ValueError("Error: Environment variable 'version_id' must be set to determine the chart version to publish.") + + new_version = f"0.0.0+{version_id}" + + logger.info(f"New helm chart version will be: {new_version}") + + if not os.path.exists(chart_path): + raise FileNotFoundError( + f"Error: Chart.yaml not found in directory '{chart_dir}'. " + "Please ensure the directory exists and contains a valid Chart.yaml." + ) + + try: + with open(chart_path, 'r') as f: + data = yaml.safe_load(f) + + chart_name = data.get('name') + if not chart_name: + raise ValueError("Chart.yaml is missing required 'name' field.") + + data['version'] = new_version + + with open(chart_path, 'w') as f: + yaml.safe_dump(data, f, sort_keys=False) + + logger.info(f"Successfully updated version for chart '{chart_name}' to '{new_version}' before publishing it.") + return chart_name, new_version + + except Exception as e: + raise RuntimeError(f"Failed to read or update Chart.yaml: {e}") + +def publish_helm_chart(): + try: + chart_name, chart_version = update_chart_and_get_metadata(CHART_DIR) + + tgz_filename = f"{chart_name}-{chart_version}.tgz" + logger.info(f"Packaging chart: {chart_name} with Version: {chart_version}") + + package_command = ["helm", "package", CHART_DIR] + run_command(package_command, f"Packaging chart '{CHART_DIR}'") + + push_command = ["helm", "push", tgz_filename, OCI_REGISTRY] + run_command(push_command, f"Pushing '{tgz_filename}' to '{OCI_REGISTRY}'") + + if os.path.exists(tgz_filename): + logger.info(f"\nCleaning up local file: {tgz_filename}") + os.remove(tgz_filename) + + logger(f"Helm Chart {chart_name}:{chart_version} was published successfully!") + except (FileNotFoundError, RuntimeError, ValueError) as e: + logger.error(f"\Failed publishing the helm chart: {e}") + +if __name__ == "__main__": + publish_helm_chart() From 982c77d64d6ed7fe18a2959d03bce7472c13ddbf Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Fri, 10 Oct 2025 16:28:08 +0200 Subject: [PATCH 02/26] Consume build_scenario via build_info for registry repo and other info --- scripts/dev/helm_registry_login.sh | 39 --------- scripts/publish_helm_chart.py | 110 +++++++++++++++++-------- scripts/release/helm_registry_login.py | 1 - 3 files changed, 75 insertions(+), 75 deletions(-) delete mode 100755 scripts/dev/helm_registry_login.sh diff --git a/scripts/dev/helm_registry_login.sh b/scripts/dev/helm_registry_login.sh deleted file mode 100755 index 1d3ca2e3f..000000000 --- a/scripts/dev/helm_registry_login.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -ECR_REGISTRY="268558157000.dkr.ecr.us-east-1.amazonaws.com" -AWS_REGION="us-east-1" - -source scripts/dev/set_env_context.sh - -export PATH=${PROJECT_DIR}/bin:$PATH - -echo "Checking if helm CLI is installed..." -if ! command -v helm &> /dev/null -then - echo "Error: helm CLI could not be found." - echo "Please ensure helm is installed and in your system's PATH." - exit 1 -fi - -echo "Checking if aws CLI is installed..." -if ! command -v aws &> /dev/null -then - echo "Error: aws CLI could not be found." - echo "Please ensure aws CLI is installed and configured." - exit 1 -fi - -echo "Logging into OCI Registry: ${ECR_REGISTRY} in region ${AWS_REGION}..." - -if aws ecr get-login-password --region "$AWS_REGION" | helm registry login \ - --username AWS \ - --password-stdin \ - "$ECR_REGISTRY" -then - echo "Helm successfully logged into the OCI registry." - exit 0 -else - echo "ERROR: Helm login to ECR registry failed." - echo "Please ensure your AWS credentials have permission to access ECR in the specified region." - exit 1 -fi diff --git a/scripts/publish_helm_chart.py b/scripts/publish_helm_chart.py index 7b7eb0a9c..ad241bf53 100644 --- a/scripts/publish_helm_chart.py +++ b/scripts/publish_helm_chart.py @@ -1,31 +1,39 @@ -import subprocess import os +import subprocess +import sys + import yaml from lib.base_logger import logger +from scripts.release.build.build_info import * CHART_DIR = "helm_chart" -OCI_REGISTRY = "oci://268558157000.dkr.ecr.us-east-1.amazonaws.com/dev/helm-charts" -def run_command(command: list[str], description: str): +def run_command(command: list[str]): try: - subprocess.run(command, check=True, text=True, capture_output=False) - logger.info(f"Command {' '.join(command)} executed successfully.") + # Using capture_output=True to grab stdout/stderr for better error logging. + process = subprocess.run(command, check=True, text=True, capture_output=True) + logger.info(f"Successfully executed: {' '.join(command)}") + if process.stdout: + logger.info(process.stdout) except subprocess.CalledProcessError as e: - logger.error(f"Error executing command: {' '.join(command)}") - raise RuntimeError(f"{description} failed.") from e + raise RuntimeError(f"Command {' '.join(command)} failed. Stderr: {e.stderr.strip()}") from e except FileNotFoundError: - raise FileNotFoundError("Error: 'helm' command not found. Ensure Helm CLI is installed and in your PATH.") + raise FileNotFoundError(f"Error: {command[0]} command not found. Ensure {command[0]} is installed and in your PATH.") + +# update_chart_and_get_metadata updates the helm chart's Chart.yaml and sets the version +# to either evg patch id or commit which is set in OPERATOR_VERSION. def update_chart_and_get_metadata(chart_dir: str) -> tuple[str, str]: chart_path = os.path.join(chart_dir, "Chart.yaml") - version_id = os.environ.get('version_id') + version_id = os.environ.get("OPERATOR_VERSION") if not version_id: - raise ValueError("Error: Environment variable 'version_id' must be set to determine the chart version to publish.") - - new_version = f"0.0.0+{version_id}" + raise ValueError( + "Error: Environment variable 'OPERATOR_VERSION' must be set to determine the chart version to publish." + ) + new_version = f"0.0.0+{version_id}" logger.info(f"New helm chart version will be: {new_version}") if not os.path.exists(chart_path): @@ -35,44 +43,76 @@ def update_chart_and_get_metadata(chart_dir: str) -> tuple[str, str]: ) try: - with open(chart_path, 'r') as f: + with open(chart_path, "r") as f: data = yaml.safe_load(f) - chart_name = data.get('name') + chart_name = data.get("name") if not chart_name: - raise ValueError("Chart.yaml is missing required 'name' field.") + raise ValueError("Chart.yaml is missing required 'name' field.") - data['version'] = new_version - - with open(chart_path, 'w') as f: - yaml.safe_dump(data, f, sort_keys=False) + data["version"] = new_version - logger.info(f"Successfully updated version for chart '{chart_name}' to '{new_version}' before publishing it.") - return chart_name, new_version + with open(chart_path, "w") as f: + yaml.safe_dump(data, f, sort_keys=False) + logger.info(f"Successfully updated version for chart '{chart_name}' to '{new_version}'.") + return chart_name, new_version except Exception as e: raise RuntimeError(f"Failed to read or update Chart.yaml: {e}") -def publish_helm_chart(): + +def get_oci_registry(chart_info: HelmChartInfo) -> str: + registry = chart_info.registry + repo = chart_info.repository + + if not registry: + raise ValueError("Error: registry doesn't seem to be set in HelmChartInfo.") + + if not repo: + raise ValueError("Error: reposiotry doesn't seem to be set in HelmChartInfo.") + + + oci_registry = f"oci://{registry}/{repo}" + logger.info(f"Determined OCI Registry: {oci_registry}") + return oci_registry + + +def publish_helm_chart(chart_info: HelmChartInfo): try: + oci_registry = get_oci_registry(chart_info) chart_name, chart_version = update_chart_and_get_metadata(CHART_DIR) - tgz_filename = f"{chart_name}-{chart_version}.tgz" - logger.info(f"Packaging chart: {chart_name} with Version: {chart_version}") - package_command = ["helm", "package", CHART_DIR] - run_command(package_command, f"Packaging chart '{CHART_DIR}'") + try: + logger.info(f"Packaging chart: {chart_name} with Version: {chart_version}") + package_command = ["helm", "package", CHART_DIR] + run_command(package_command) + + logger.info(f"Pushing chart to registry: {oci_registry}") + push_command = ["helm", "push", tgz_filename, oci_registry] + run_command(push_command) - push_command = ["helm", "push", tgz_filename, OCI_REGISTRY] - run_command(push_command, f"Pushing '{tgz_filename}' to '{OCI_REGISTRY}'") + logger.info(f"Helm Chart {chart_name}:{chart_version} was published successfully!") + finally: + # Cleanup the local .tgz file regardless of push success/failure + if os.path.exists(tgz_filename): + logger.info(f"Cleaning up local file: {tgz_filename}") + os.remove(tgz_filename) - if os.path.exists(tgz_filename): - logger.info(f"\nCleaning up local file: {tgz_filename}") - os.remove(tgz_filename) - - logger(f"Helm Chart {chart_name}:{chart_version} was published successfully!") except (FileNotFoundError, RuntimeError, ValueError) as e: - logger.error(f"\Failed publishing the helm chart: {e}") + raise Exception(f"Failed publishing the helm chart {e}") + + +def main(): + build_scenario = os.environ.get("BUILD_SCENARIO") + build_info = load_build_info(build_scenario) + + return publish_helm_chart(build_info.helm_charts["mongodb-kubernetes"]) + if __name__ == "__main__": - publish_helm_chart() + try: + main() + except Exception as e: + logger.error(f"Failure in the helm publishing process {e}") + sys.exit(1) diff --git a/scripts/release/helm_registry_login.py b/scripts/release/helm_registry_login.py index 4abf08864..93192b466 100644 --- a/scripts/release/helm_registry_login.py +++ b/scripts/release/helm_registry_login.py @@ -69,7 +69,6 @@ def main(): region = build_info.helm_charts["mongodb-kubernetes"].region return helm_registry_login(registry, region) - if __name__ == "__main__": try: main() From 0daaf61f68b22c4a0ec0bef1fa2ace34d1636921 Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Fri, 10 Oct 2025 16:40:45 +0200 Subject: [PATCH 03/26] Run precommit --- scripts/publish_helm_chart.py | 5 +++-- scripts/release/helm_registry_login.py | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/publish_helm_chart.py b/scripts/publish_helm_chart.py index ad241bf53..1796d344f 100644 --- a/scripts/publish_helm_chart.py +++ b/scripts/publish_helm_chart.py @@ -20,7 +20,9 @@ def run_command(command: list[str]): except subprocess.CalledProcessError as e: raise RuntimeError(f"Command {' '.join(command)} failed. Stderr: {e.stderr.strip()}") from e except FileNotFoundError: - raise FileNotFoundError(f"Error: {command[0]} command not found. Ensure {command[0]} is installed and in your PATH.") + raise FileNotFoundError( + f"Error: {command[0]} command not found. Ensure {command[0]} is installed and in your PATH." + ) # update_chart_and_get_metadata updates the helm chart's Chart.yaml and sets the version @@ -71,7 +73,6 @@ def get_oci_registry(chart_info: HelmChartInfo) -> str: if not repo: raise ValueError("Error: reposiotry doesn't seem to be set in HelmChartInfo.") - oci_registry = f"oci://{registry}/{repo}" logger.info(f"Determined OCI Registry: {oci_registry}") return oci_registry diff --git a/scripts/release/helm_registry_login.py b/scripts/release/helm_registry_login.py index 93192b466..4abf08864 100644 --- a/scripts/release/helm_registry_login.py +++ b/scripts/release/helm_registry_login.py @@ -69,6 +69,7 @@ def main(): region = build_info.helm_charts["mongodb-kubernetes"].region return helm_registry_login(registry, region) + if __name__ == "__main__": try: main() From 4c753fcab93f29ae5f4efb05137882a17df55354 Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Tue, 14 Oct 2025 17:58:42 +0200 Subject: [PATCH 04/26] Address review comments 1. Move file from scripts to scripts/relese 2. call python files from .sh files so that we can use build_scenario env var --- scripts/publish_helm_chart.py | 119 ---------------------------------- 1 file changed, 119 deletions(-) delete mode 100644 scripts/publish_helm_chart.py diff --git a/scripts/publish_helm_chart.py b/scripts/publish_helm_chart.py deleted file mode 100644 index 1796d344f..000000000 --- a/scripts/publish_helm_chart.py +++ /dev/null @@ -1,119 +0,0 @@ -import os -import subprocess -import sys - -import yaml - -from lib.base_logger import logger -from scripts.release.build.build_info import * - -CHART_DIR = "helm_chart" - - -def run_command(command: list[str]): - try: - # Using capture_output=True to grab stdout/stderr for better error logging. - process = subprocess.run(command, check=True, text=True, capture_output=True) - logger.info(f"Successfully executed: {' '.join(command)}") - if process.stdout: - logger.info(process.stdout) - except subprocess.CalledProcessError as e: - raise RuntimeError(f"Command {' '.join(command)} failed. Stderr: {e.stderr.strip()}") from e - except FileNotFoundError: - raise FileNotFoundError( - f"Error: {command[0]} command not found. Ensure {command[0]} is installed and in your PATH." - ) - - -# update_chart_and_get_metadata updates the helm chart's Chart.yaml and sets the version -# to either evg patch id or commit which is set in OPERATOR_VERSION. -def update_chart_and_get_metadata(chart_dir: str) -> tuple[str, str]: - chart_path = os.path.join(chart_dir, "Chart.yaml") - version_id = os.environ.get("OPERATOR_VERSION") - if not version_id: - raise ValueError( - "Error: Environment variable 'OPERATOR_VERSION' must be set to determine the chart version to publish." - ) - - new_version = f"0.0.0+{version_id}" - logger.info(f"New helm chart version will be: {new_version}") - - if not os.path.exists(chart_path): - raise FileNotFoundError( - f"Error: Chart.yaml not found in directory '{chart_dir}'. " - "Please ensure the directory exists and contains a valid Chart.yaml." - ) - - try: - with open(chart_path, "r") as f: - data = yaml.safe_load(f) - - chart_name = data.get("name") - if not chart_name: - raise ValueError("Chart.yaml is missing required 'name' field.") - - data["version"] = new_version - - with open(chart_path, "w") as f: - yaml.safe_dump(data, f, sort_keys=False) - - logger.info(f"Successfully updated version for chart '{chart_name}' to '{new_version}'.") - return chart_name, new_version - except Exception as e: - raise RuntimeError(f"Failed to read or update Chart.yaml: {e}") - - -def get_oci_registry(chart_info: HelmChartInfo) -> str: - registry = chart_info.registry - repo = chart_info.repository - - if not registry: - raise ValueError("Error: registry doesn't seem to be set in HelmChartInfo.") - - if not repo: - raise ValueError("Error: reposiotry doesn't seem to be set in HelmChartInfo.") - - oci_registry = f"oci://{registry}/{repo}" - logger.info(f"Determined OCI Registry: {oci_registry}") - return oci_registry - - -def publish_helm_chart(chart_info: HelmChartInfo): - try: - oci_registry = get_oci_registry(chart_info) - chart_name, chart_version = update_chart_and_get_metadata(CHART_DIR) - tgz_filename = f"{chart_name}-{chart_version}.tgz" - - try: - logger.info(f"Packaging chart: {chart_name} with Version: {chart_version}") - package_command = ["helm", "package", CHART_DIR] - run_command(package_command) - - logger.info(f"Pushing chart to registry: {oci_registry}") - push_command = ["helm", "push", tgz_filename, oci_registry] - run_command(push_command) - - logger.info(f"Helm Chart {chart_name}:{chart_version} was published successfully!") - finally: - # Cleanup the local .tgz file regardless of push success/failure - if os.path.exists(tgz_filename): - logger.info(f"Cleaning up local file: {tgz_filename}") - os.remove(tgz_filename) - - except (FileNotFoundError, RuntimeError, ValueError) as e: - raise Exception(f"Failed publishing the helm chart {e}") - - -def main(): - build_scenario = os.environ.get("BUILD_SCENARIO") - build_info = load_build_info(build_scenario) - - return publish_helm_chart(build_info.helm_charts["mongodb-kubernetes"]) - - -if __name__ == "__main__": - try: - main() - except Exception as e: - logger.error(f"Failure in the helm publishing process {e}") - sys.exit(1) From 8b511e5c9baa106ba1c4fa121c9ffab2697fc9e6 Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Wed, 8 Oct 2025 16:10:57 +0200 Subject: [PATCH 05/26] Publish helm chart to OCI registry for PR patches --- .evergreen.yml | 10 ++++++++ scripts/dev/helm_registry_login.sh | 39 ++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100755 scripts/dev/helm_registry_login.sh diff --git a/.evergreen.yml b/.evergreen.yml index f99cc4c41..afc0683aa 100644 --- a/.evergreen.yml +++ b/.evergreen.yml @@ -468,6 +468,16 @@ tasks: - func: helm_registry_login - func: publish_helm_chart + - name: publish_helm_chart + commands: + - func: clone + - func: setup_kubectl + - func: setup_aws + - func: prepare_aws + - func: helm_registry_login + - func: python_venv + - func: publish_helm_chart + - name: prepare_aws priority: 59 commands: diff --git a/scripts/dev/helm_registry_login.sh b/scripts/dev/helm_registry_login.sh new file mode 100755 index 000000000..1d3ca2e3f --- /dev/null +++ b/scripts/dev/helm_registry_login.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +ECR_REGISTRY="268558157000.dkr.ecr.us-east-1.amazonaws.com" +AWS_REGION="us-east-1" + +source scripts/dev/set_env_context.sh + +export PATH=${PROJECT_DIR}/bin:$PATH + +echo "Checking if helm CLI is installed..." +if ! command -v helm &> /dev/null +then + echo "Error: helm CLI could not be found." + echo "Please ensure helm is installed and in your system's PATH." + exit 1 +fi + +echo "Checking if aws CLI is installed..." +if ! command -v aws &> /dev/null +then + echo "Error: aws CLI could not be found." + echo "Please ensure aws CLI is installed and configured." + exit 1 +fi + +echo "Logging into OCI Registry: ${ECR_REGISTRY} in region ${AWS_REGION}..." + +if aws ecr get-login-password --region "$AWS_REGION" | helm registry login \ + --username AWS \ + --password-stdin \ + "$ECR_REGISTRY" +then + echo "Helm successfully logged into the OCI registry." + exit 0 +else + echo "ERROR: Helm login to ECR registry failed." + echo "Please ensure your AWS credentials have permission to access ECR in the specified region." + exit 1 +fi From 4f50441cc27f6c42a8b88df8c37df914d3b7405c Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Wed, 8 Oct 2025 16:39:43 +0200 Subject: [PATCH 06/26] Install published helm chart instead of local one, during E2E --- .evergreen.yml | 2 + docker/mongodb-kubernetes-tests/Dockerfile | 8 +- .../kubetester/helm.py | 84 ++++++++++++++++++- 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/.evergreen.yml b/.evergreen.yml index afc0683aa..dfafaa5c0 100644 --- a/.evergreen.yml +++ b/.evergreen.yml @@ -54,6 +54,8 @@ variables: variant: init_test_run - name: build_init_appdb_images_ubi variant: init_test_run + - name: publish_helm_chart + variant: init_test_run - &community_dependency depends_on: diff --git a/docker/mongodb-kubernetes-tests/Dockerfile b/docker/mongodb-kubernetes-tests/Dockerfile index 88be6b11d..dd1b8aca7 100644 --- a/docker/mongodb-kubernetes-tests/Dockerfile +++ b/docker/mongodb-kubernetes-tests/Dockerfile @@ -45,7 +45,8 @@ RUN apt-get -qq update \ libldap2-dev \ libsasl2-dev \ git \ - openssl + openssl \ + unzip RUN mkdir -p /tmp/mongodb-tools && \ tar xfz /tmp/mongodb-tools.tgz -C /tmp/mongodb-tools && \ @@ -66,6 +67,11 @@ RUN curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl - && chmod +x ./kubectl \ && mv ./kubectl /usr/local/bin/kubectl +# install aws, required to run helm registry login while running the tests +RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \ + && unzip -q awscliv2.zip \ + && ./aws/install + COPY --from=builder /venv /venv ENV PATH="/venv/bin:${PATH}" diff --git a/docker/mongodb-kubernetes-tests/kubetester/helm.py b/docker/mongodb-kubernetes-tests/kubetester/helm.py index 9e0cca8fe..60829ab2f 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/helm.py +++ b/docker/mongodb-kubernetes-tests/kubetester/helm.py @@ -10,6 +10,8 @@ logger = test_logger.get_test_logger(__name__) +HELM_REGISTRY_AWS_REGION = "us-east-1" +HELM_ECR_REGISTRY = "268558157000.dkr.ecr.us-east-1.amazonaws.com" def helm_template( helm_args: Dict, @@ -162,8 +164,14 @@ def helm_upgrade( chart_dir = helm_chart_path if helm_override_path else _helm_chart_dir(helm_chart_path) if apply_crds_first: + # right now tests image has the entire helm_chart directory, maybe we should just copy the CRDs apply_crds_from_chart(chart_dir) + # login to helm registry because we are going to install published helm chart + if not helm_registry_login(): + raise Exception(f"Failed logging in to the helm registry {HELM_ECR_REGISTRY}") + + chart_dir = f"oci://{HELM_ECR_REGISTRY}/dev/helm-charts/mongodb-kubernetes" command_args = _create_helm_args(helm_args, helm_options) args = [ "helm", @@ -173,7 +181,7 @@ def helm_upgrade( *command_args, name, ] - + custom_operator_version = "0.0.0+68e3eec04df1df00072e1bb2" if custom_operator_version: args.append(f"--version={custom_operator_version}") @@ -182,6 +190,80 @@ def helm_upgrade( command = " ".join(args) process_run_and_check(command, check=True, capture_output=True, shell=True) +def helm_registry_login(): + logger.info(f"Attempting to log into ECR registry: {HELM_ECR_REGISTRY}, using helm registry login.") + + aws_command = [ + "aws", + "ecr", + "get-login-password", + "--region", + HELM_REGISTRY_AWS_REGION + ] + + # as we can see the password is being provided by stdin, that would mean we will have to + # pipe the aws_command (it figures out the password) into helm_command. + helm_command = [ + "helm", + "registry", + "login", + "--username", + "AWS", + "--password-stdin", + HELM_ECR_REGISTRY + ] + + try: + logger.info("Starting AWS ECR credential retrieval.") + aws_proc = subprocess.Popen( + aws_command, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True # Treat input/output as text strings + ) + + logger.info("Starting Helm registry login.") + helm_proc = subprocess.Popen( + helm_command, + stdin=aws_proc.stdout, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True + ) + + # Close the stdout stream of aws_proc in the parent process + # to prevent resource leakage (only needed if you plan to do more processing) + aws_proc.stdout.close() + + # Wait for the Helm command (helm_proc) to finish and capture its output + helm_stdout, helm_stderr = helm_proc.communicate() + + # Wait for the AWS process to finish as well + aws_proc.wait() + + if aws_proc.returncode != 0: + logger.error(f"aws command to get password failed, (Exit Code {aws_proc.returncode}).") + # We captured AWS stderr directly, so print it + _, aws_stderr = aws_proc.communicate() + logger.error(aws_stderr) + return False + + if helm_proc.returncode == 0: + logger.info("Login to helm registry was successful.") + logger.info(helm_stdout.strip()) + return True + else: + logger.error(f"Login to helm registry failed, (Exit Code {helm_proc.returncode}).") + logger.error(helm_stderr.strip()) + return False + + except FileNotFoundError as e: + # This catches errors if 'aws' or 'helm' are not in the PATH + logger.error(f"Command not found. Please ensure '{e.filename}' is installed and in your system's PATH.") + return False + except Exception as e: + logger.error(f"An unexpected error occurred: {e}.") + return False def apply_crds_from_chart(chart_dir: str): crd_files = glob.glob(os.path.join(chart_dir, "crds", "*.yaml")) From 087e06aeb5eb989feaa7628901c7d182b97418c3 Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Wed, 8 Oct 2025 17:47:41 +0200 Subject: [PATCH 07/26] Don't copy entire helm_chart dir, just copy CRDs --- docker/mongodb-kubernetes-tests/Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docker/mongodb-kubernetes-tests/Dockerfile b/docker/mongodb-kubernetes-tests/Dockerfile index dd1b8aca7..b91ef0516 100644 --- a/docker/mongodb-kubernetes-tests/Dockerfile +++ b/docker/mongodb-kubernetes-tests/Dockerfile @@ -81,8 +81,9 @@ WORKDIR /tests # copying the test files after python build, otherwise pip install will be called each time the tests change COPY . /tests -# copying the helm_chart directory as well to support installation of the Operator from the test application -COPY helm_chart /helm_chart +# copying the helm_chart/crds directory so that we can install CRDs before installing the operator helm chart to run a test. +# operator is installed via published OCI helm repo and not the local helm repo. +COPY helm_chart/crds /helm_chart/crds COPY release.json /release.json # we use the public directory to automatically test resources samples COPY public /mongodb-kubernetes/public From cb2a8d24fda7e49bbd54f7d2fe8068c9191879bf Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Fri, 10 Oct 2025 17:00:24 +0200 Subject: [PATCH 08/26] Delete not needed file --- scripts/dev/helm_registry_login.sh | 39 ------------------------------ 1 file changed, 39 deletions(-) delete mode 100755 scripts/dev/helm_registry_login.sh diff --git a/scripts/dev/helm_registry_login.sh b/scripts/dev/helm_registry_login.sh deleted file mode 100755 index 1d3ca2e3f..000000000 --- a/scripts/dev/helm_registry_login.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -ECR_REGISTRY="268558157000.dkr.ecr.us-east-1.amazonaws.com" -AWS_REGION="us-east-1" - -source scripts/dev/set_env_context.sh - -export PATH=${PROJECT_DIR}/bin:$PATH - -echo "Checking if helm CLI is installed..." -if ! command -v helm &> /dev/null -then - echo "Error: helm CLI could not be found." - echo "Please ensure helm is installed and in your system's PATH." - exit 1 -fi - -echo "Checking if aws CLI is installed..." -if ! command -v aws &> /dev/null -then - echo "Error: aws CLI could not be found." - echo "Please ensure aws CLI is installed and configured." - exit 1 -fi - -echo "Logging into OCI Registry: ${ECR_REGISTRY} in region ${AWS_REGION}..." - -if aws ecr get-login-password --region "$AWS_REGION" | helm registry login \ - --username AWS \ - --password-stdin \ - "$ECR_REGISTRY" -then - echo "Helm successfully logged into the OCI registry." - exit 0 -else - echo "ERROR: Helm login to ECR registry failed." - echo "Please ensure your AWS credentials have permission to access ECR in the specified region." - exit 1 -fi From b1162ec698072e9bcefa80444f2dfd5e2a7e91ef Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Wed, 15 Oct 2025 16:36:21 +0200 Subject: [PATCH 09/26] Start installing chart from OCI registry in E2E --- .evergreen.yml | 10 -- .../kubetester/helm.py | 147 ++++++++---------- .../templates/mongodb-enterprise-tests.yaml | 16 ++ .../deployments/test-app/values.yaml | 11 ++ scripts/evergreen/e2e/single_e2e.sh | 21 +++ scripts/release/oci_chart_info.py | 24 +++ 6 files changed, 139 insertions(+), 90 deletions(-) create mode 100644 scripts/release/oci_chart_info.py diff --git a/.evergreen.yml b/.evergreen.yml index dfafaa5c0..ba802f58f 100644 --- a/.evergreen.yml +++ b/.evergreen.yml @@ -470,16 +470,6 @@ tasks: - func: helm_registry_login - func: publish_helm_chart - - name: publish_helm_chart - commands: - - func: clone - - func: setup_kubectl - - func: setup_aws - - func: prepare_aws - - func: helm_registry_login - - func: python_venv - - func: publish_helm_chart - - name: prepare_aws priority: 59 commands: diff --git a/docker/mongodb-kubernetes-tests/kubetester/helm.py b/docker/mongodb-kubernetes-tests/kubetester/helm.py index 60829ab2f..117665439 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/helm.py +++ b/docker/mongodb-kubernetes-tests/kubetester/helm.py @@ -10,9 +10,6 @@ logger = test_logger.get_test_logger(__name__) -HELM_REGISTRY_AWS_REGION = "us-east-1" -HELM_ECR_REGISTRY = "268558157000.dkr.ecr.us-east-1.amazonaws.com" - def helm_template( helm_args: Dict, helm_chart_path: Optional[str] = "helm_chart", @@ -146,6 +143,53 @@ def process_run_and_check(args, **kwargs): logger.error(f"output: {exc.output}") raise +def oci_helm_registry_login(helm_registry: str, region: str): + logger.info(f"Attempting to log into ECR registry: {helm_registry}, using helm registry login.") + + aws_command = ["aws", "ecr", "get-login-password", "--region", region] + + # as we can see the password is being provided by stdin, that would mean we will have to + # pipe the aws_command (it figures out the password) into helm_command. + helm_command = ["helm", "registry", "login", "--username", "AWS", "--password-stdin", helm_registry] + + try: + logger.info("Starting AWS ECR credential retrieval.") + aws_proc = subprocess.Popen( + aws_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True # Treat input/output as text strings + ) + + logger.info("Starting Helm registry login.") + helm_proc = subprocess.Popen( + helm_command, stdin=aws_proc.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True + ) + + # Close the stdout stream of aws_proc in the parent process + # to prevent resource leakage (only needed if you plan to do more processing) + aws_proc.stdout.close() + + # Wait for the Helm command (helm_proc) to finish and capture its output + helm_stdout, helm_stderr = helm_proc.communicate() + + # Wait for the AWS process to finish as well + aws_proc.wait() + + if aws_proc.returncode != 0: + _, aws_stderr = aws_proc.communicate() + raise Exception(f"aws command to get password failed. Error: {aws_stderr}") + + if helm_proc.returncode == 0: + logger.info("Login to helm registry was successful.") + logger.info(helm_stdout.strip()) + else: + raise Exception( + f"Login to helm registry failed, Exit code: {helm_proc.returncode}, Error: {helm_stderr.strip()}" + ) + + except FileNotFoundError as e: + # This catches errors if 'aws' or 'helm' are not in the PATH + raise Exception(f"Command not found. Please ensure '{e.filename}' is installed and in your system's PATH.") + except Exception as e: + raise Exception(f"An unexpected error occurred: {e}.") def helm_upgrade( name: str, @@ -168,10 +212,14 @@ def helm_upgrade( apply_crds_from_chart(chart_dir) # login to helm registry because we are going to install published helm chart - if not helm_registry_login(): - raise Exception(f"Failed logging in to the helm registry {HELM_ECR_REGISTRY}") + try: + registry, repository, region = oci_chart_info() + + oci_helm_registry_login(registry, region) + except Exception as e: + raise Exception(f"Failed logging in to the helm registry {registry}. Error: {e}") - chart_dir = f"oci://{HELM_ECR_REGISTRY}/dev/helm-charts/mongodb-kubernetes" + chart_uri = f"oci://{registry}/{repository}" command_args = _create_helm_args(helm_args, helm_options) args = [ "helm", @@ -181,89 +229,28 @@ def helm_upgrade( *command_args, name, ] - custom_operator_version = "0.0.0+68e3eec04df1df00072e1bb2" + if custom_operator_version: args.append(f"--version={custom_operator_version}") + else: + published_chart_version = os.environ.get("OPERATOR_VERSION") + if not published_chart_version: + logger.info("OPERATOR_VERSION env var is not set") + args.append(f"--version=0.0.0+{published_chart_version}") - args.append(chart_dir) + args.append(chart_uri) command = " ".join(args) process_run_and_check(command, check=True, capture_output=True, shell=True) -def helm_registry_login(): - logger.info(f"Attempting to log into ECR registry: {HELM_ECR_REGISTRY}, using helm registry login.") - - aws_command = [ - "aws", - "ecr", - "get-login-password", - "--region", - HELM_REGISTRY_AWS_REGION - ] - - # as we can see the password is being provided by stdin, that would mean we will have to - # pipe the aws_command (it figures out the password) into helm_command. - helm_command = [ - "helm", - "registry", - "login", - "--username", - "AWS", - "--password-stdin", - HELM_ECR_REGISTRY - ] +def oci_chart_info(): + registry = os.environ.get("OCI_HELM_REGISTRY") + repository = os.environ.get("OCI_HELM_REPOSITORY") + region = os.environ.get("OCI_HELM_REGION") - try: - logger.info("Starting AWS ECR credential retrieval.") - aws_proc = subprocess.Popen( - aws_command, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True # Treat input/output as text strings - ) - - logger.info("Starting Helm registry login.") - helm_proc = subprocess.Popen( - helm_command, - stdin=aws_proc.stdout, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True - ) - - # Close the stdout stream of aws_proc in the parent process - # to prevent resource leakage (only needed if you plan to do more processing) - aws_proc.stdout.close() - - # Wait for the Helm command (helm_proc) to finish and capture its output - helm_stdout, helm_stderr = helm_proc.communicate() - - # Wait for the AWS process to finish as well - aws_proc.wait() - - if aws_proc.returncode != 0: - logger.error(f"aws command to get password failed, (Exit Code {aws_proc.returncode}).") - # We captured AWS stderr directly, so print it - _, aws_stderr = aws_proc.communicate() - logger.error(aws_stderr) - return False - - if helm_proc.returncode == 0: - logger.info("Login to helm registry was successful.") - logger.info(helm_stdout.strip()) - return True - else: - logger.error(f"Login to helm registry failed, (Exit Code {helm_proc.returncode}).") - logger.error(helm_stderr.strip()) - return False + print(f"oci chart details in test image is registry {registry}, repo {repository}, region {region}") - except FileNotFoundError as e: - # This catches errors if 'aws' or 'helm' are not in the PATH - logger.error(f"Command not found. Please ensure '{e.filename}' is installed and in your system's PATH.") - return False - except Exception as e: - logger.error(f"An unexpected error occurred: {e}.") - return False + return registry, f"{repository}/mongodb-kubernetes", region def apply_crds_from_chart(chart_dir: str): crd_files = glob.glob(os.path.join(chart_dir, "crds", "*.yaml")) diff --git a/scripts/evergreen/deployments/test-app/templates/mongodb-enterprise-tests.yaml b/scripts/evergreen/deployments/test-app/templates/mongodb-enterprise-tests.yaml index 2a3e37ff3..7abfd58ab 100644 --- a/scripts/evergreen/deployments/test-app/templates/mongodb-enterprise-tests.yaml +++ b/scripts/evergreen/deployments/test-app/templates/mongodb-enterprise-tests.yaml @@ -174,6 +174,22 @@ spec: - name: OM_DEBUG_HTTP value: "{{ .Values.omDebugHttp }}" {{ end }} + {{ if .Values.helm.oci.registry }} + - name: OCI_HELM_REGISTRY + value: "{{ .Values.helm.oci.registry }}" + {{ end }} + {{ if .Values.operator.version }} + - name: OPERATOR_VERSION + value: "{{ .Values.operator.version }}" + {{ end }} + {{ if .Values.helm.oci.repository }} + - name: OCI_HELM_REPOSITORY + value: "{{ .Values.helm.oci.repository }}" + {{ end }} + {{ if .Values.helm.oci.region }} + - name: OCI_HELM_REGION + value: "{{ .Values.helm.oci.region }}" + {{ end }} - name: ops_manager_version value: "{{ .Values.opsManagerVersion }}" - name: cognito_user_pool_id diff --git a/scripts/evergreen/deployments/test-app/values.yaml b/scripts/evergreen/deployments/test-app/values.yaml index 13aba3df8..09ab966c7 100644 --- a/scripts/evergreen/deployments/test-app/values.yaml +++ b/scripts/evergreen/deployments/test-app/values.yaml @@ -43,3 +43,14 @@ mdbImageType: "ubi8" # set to "true" to set OM_DEBUG_HTTP=true for the operator omDebugHttp: + +# sets the configuration using which we can figure out the helm OCI repo of the MCK operator while deploying it +# to run a test. +helm: + oci: + registry: "" + repository: "" + region: "" + +operator: + version: "" diff --git a/scripts/evergreen/e2e/single_e2e.sh b/scripts/evergreen/e2e/single_e2e.sh index 05277f914..30effa4c1 100755 --- a/scripts/evergreen/e2e/single_e2e.sh +++ b/scripts/evergreen/e2e/single_e2e.sh @@ -48,6 +48,11 @@ deploy_test_app() { BUILD_ID="${BUILD_ID:-default_build_id}" BUILD_VARIANT="${BUILD_VARIANT:-default_build_variant}" + chart_info=$(scripts/dev/run_python.sh scripts/release/oci_chart_info.py) + helm_oci_regisry=$(echo "$chart_info" | jq -r '.registry' ) + helm_oci_repository=$(echo "$chart_info" | jq -r '.repository' ) + helm_oci_registry_region=$(echo "$chart_info" | jq -r '.region' ) + # note, that the 4 last parameters are used only for Mongodb resource testing - not for Ops Manager helm_params=( "--set" "taskId=${task_id:-'not-specified'}" @@ -142,6 +147,22 @@ deploy_test_app() { helm_params+=("--set" "omDebugHttp=true") fi + if [[ -n "${helm_oci_regisry:-}" ]]; then + helm_params+=("--set" "helm.oci.registry=${helm_oci_regisry}") + fi + + if [[ -n "${helm_oci_repository:-}" ]]; then + helm_params+=("--set" "helm.oci.repository=${helm_oci_repository}") + fi + + if [[ -n "${helm_oci_registry_region:-}" ]]; then + helm_params+=("--set" "helm.oci.region=${helm_oci_registry_region}") + fi + + if [[ -n "${OPERATOR_VERSION:-}" ]]; then + helm_params+=("--set" "operator.version=${OPERATOR_VERSION}") + fi + helm_params+=("--set" "opsManagerVersion=${ops_manager_version}") helm template "scripts/evergreen/deployments/test-app" "${helm_params[@]}" > "${helm_template_file}" || exit 1 diff --git a/scripts/release/oci_chart_info.py b/scripts/release/oci_chart_info.py new file mode 100644 index 000000000..7272658c6 --- /dev/null +++ b/scripts/release/oci_chart_info.py @@ -0,0 +1,24 @@ +import os +import sys +import json + +from dataclasses import asdict +from lib.base_logger import logger +from scripts.release.build.build_info import load_build_info + +def main(): + build_scenario = os.environ.get("BUILD_SCENARIO") + build_info = load_build_info(build_scenario) + chart_info = build_info.helm_charts["mongodb-kubernetes"] + + j = json.dumps(asdict(chart_info)) + print(j) + + + +if __name__ == "__main__": + try: + main() + except Exception as e: + logger.error(f"Failed while dumping the chart_info as json. Error: {e}") + sys.exit(1) \ No newline at end of file From 8a5002070b1bf36153631af398d9aff3c064e5fc Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Wed, 15 Oct 2025 16:43:34 +0200 Subject: [PATCH 10/26] Add newline --- scripts/release/oci_chart_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/release/oci_chart_info.py b/scripts/release/oci_chart_info.py index 7272658c6..0e5b6bf54 100644 --- a/scripts/release/oci_chart_info.py +++ b/scripts/release/oci_chart_info.py @@ -21,4 +21,4 @@ def main(): main() except Exception as e: logger.error(f"Failed while dumping the chart_info as json. Error: {e}") - sys.exit(1) \ No newline at end of file + sys.exit(1) From c04e43a8be97e846203e80d6b439370a503d2ce8 Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Thu, 16 Oct 2025 13:57:25 +0200 Subject: [PATCH 11/26] Refactor 1. Move figuring out of chart dir from helm.py to other places to Operator() and _install_multi_cluster_operator 2. Run precommit --- .../kubetester/helm.py | 24 +++++---------- .../kubetester/operator.py | 30 +++++++++++++++++-- .../tests/conftest.py | 28 +++++++++++++++-- scripts/evergreen/e2e/single_e2e.sh | 6 ++-- scripts/release/oci_chart_info.py | 6 ++-- 5 files changed, 65 insertions(+), 29 deletions(-) diff --git a/docker/mongodb-kubernetes-tests/kubetester/helm.py b/docker/mongodb-kubernetes-tests/kubetester/helm.py index 117665439..40533b2b6 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/helm.py +++ b/docker/mongodb-kubernetes-tests/kubetester/helm.py @@ -10,6 +10,7 @@ logger = test_logger.get_test_logger(__name__) + def helm_template( helm_args: Dict, helm_chart_path: Optional[str] = "helm_chart", @@ -143,6 +144,7 @@ def process_run_and_check(args, **kwargs): logger.error(f"output: {exc.output}") raise + def oci_helm_registry_login(helm_registry: str, region: str): logger.info(f"Attempting to log into ECR registry: {helm_registry}, using helm registry login.") @@ -191,6 +193,7 @@ def oci_helm_registry_login(helm_registry: str, region: str): except Exception as e: raise Exception(f"An unexpected error occurred: {e}.") + def helm_upgrade( name: str, namespace: str, @@ -208,18 +211,8 @@ def helm_upgrade( chart_dir = helm_chart_path if helm_override_path else _helm_chart_dir(helm_chart_path) if apply_crds_first: - # right now tests image has the entire helm_chart directory, maybe we should just copy the CRDs apply_crds_from_chart(chart_dir) - # login to helm registry because we are going to install published helm chart - try: - registry, repository, region = oci_chart_info() - - oci_helm_registry_login(registry, region) - except Exception as e: - raise Exception(f"Failed logging in to the helm registry {registry}. Error: {e}") - - chart_uri = f"oci://{registry}/{repository}" command_args = _create_helm_args(helm_args, helm_options) args = [ "helm", @@ -229,20 +222,16 @@ def helm_upgrade( *command_args, name, ] - + if custom_operator_version: args.append(f"--version={custom_operator_version}") - else: - published_chart_version = os.environ.get("OPERATOR_VERSION") - if not published_chart_version: - logger.info("OPERATOR_VERSION env var is not set") - args.append(f"--version=0.0.0+{published_chart_version}") - args.append(chart_uri) + args.append(chart_dir) command = " ".join(args) process_run_and_check(command, check=True, capture_output=True, shell=True) + def oci_chart_info(): registry = os.environ.get("OCI_HELM_REGISTRY") repository = os.environ.get("OCI_HELM_REPOSITORY") @@ -252,6 +241,7 @@ def oci_chart_info(): return registry, f"{repository}/mongodb-kubernetes", region + def apply_crds_from_chart(chart_dir: str): crd_files = glob.glob(os.path.join(chart_dir, "crds", "*.yaml")) diff --git a/docker/mongodb-kubernetes-tests/kubetester/operator.py b/docker/mongodb-kubernetes-tests/kubetester/operator.py index fa2b90344..f75a321fb 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/operator.py +++ b/docker/mongodb-kubernetes-tests/kubetester/operator.py @@ -1,6 +1,7 @@ from __future__ import annotations import logging +import os import time from typing import Dict, List, Optional @@ -16,6 +17,8 @@ helm_template, helm_uninstall, helm_upgrade, + oci_chart_info, + oci_helm_registry_login, ) from tests import test_logger @@ -43,13 +46,27 @@ def __init__( namespace: str, helm_args: Optional[Dict] = None, helm_options: Optional[List[str]] = None, - helm_chart_path: Optional[str] = "helm_chart", + helm_chart_path: Optional[str] = None, name: Optional[str] = "mongodb-kubernetes-operator", api_client: Optional[client.api_client.ApiClient] = None, + operator_version: Optional[str] = None, ): + if not helm_chart_path: + # login to the OCI container registry + registry, repository, region = oci_chart_info() + try: + oci_helm_registry_login(registry, region) + except Exception as e: + raise e - # The Operator will be installed from the following repo, so adding it first - helm_repo_add("mongodb", "https://mongodb.github.io/helm-charts") + # figure out the registry URI, based on dev/staging scenario + chart_uri = f"oci://{registry}/{repository}" + helm_chart_path = chart_uri + + if not operator_version: + # most probably we are trying to install current operator which will be installed + # from OCI registry. The version (dev/staging) is set in `OPERATOR_VERSION` + operator_version = os.environ.get("OPERATOR_VERSION") if helm_args is None: helm_args = {} @@ -69,6 +86,7 @@ def __init__( self.helm_chart_path = helm_chart_path self.name = name self.api_client = api_client + self.operator_version = operator_version def install_from_template(self): """Uses helm to generate yaml specification and then uses python K8s client to apply them to the cluster @@ -82,6 +100,9 @@ def install_from_template(self): def install(self, custom_operator_version: Optional[str] = None) -> Operator: """Installs the Operator to Kubernetes cluster using 'helm install', waits until it's running""" + if not custom_operator_version: + custom_operator_version = self.operator_version + helm_install( self.name, self.namespace, @@ -99,6 +120,9 @@ def upgrade( self, multi_cluster: bool = False, custom_operator_version: Optional[str] = None, apply_crds_first: bool = False ) -> Operator: """Upgrades the Operator in Kubernetes cluster using 'helm upgrade', waits until it's running""" + if not custom_operator_version: + custom_operator_version = self.operator_version + helm_upgrade( self.name, self.namespace, diff --git a/docker/mongodb-kubernetes-tests/tests/conftest.py b/docker/mongodb-kubernetes-tests/tests/conftest.py index 15366fc79..cb46e4755 100644 --- a/docker/mongodb-kubernetes-tests/tests/conftest.py +++ b/docker/mongodb-kubernetes-tests/tests/conftest.py @@ -20,7 +20,12 @@ update_configmap, ) from kubetester.awss3client import AwsS3Client -from kubetester.helm import helm_install_from_chart, helm_repo_add +from kubetester.helm import ( + helm_install_from_chart, + helm_repo_add, + oci_chart_info, + oci_helm_registry_login, +) from kubetester.kubetester import KubernetesTester from kubetester.kubetester import fixture as _fixture from kubetester.kubetester import running_locally @@ -827,14 +832,31 @@ def _install_multi_cluster_operator( helm_opts: dict[str, str], central_cluster_name: str, operator_name: Optional[str] = MULTI_CLUSTER_OPERATOR_NAME, - helm_chart_path: Optional[str] = LOCAL_HELM_CHART_DIR, + helm_chart_path: Optional[str] = None, custom_operator_version: Optional[str] = None, apply_crds_first: bool = False, ) -> Operator: multi_cluster_operator_installation_config.update(helm_opts) # The Operator will be installed from the following repo, so adding it first - helm_repo_add("mongodb", "https://mongodb.github.io/helm-charts") + # helm_repo_add("mongodb", "https://mongodb.github.io/helm-charts") + + # login to the OCI container registry + registry, repository, region = oci_chart_info() + try: + oci_helm_registry_login(registry, region) + except Exception as e: + raise e + + # figure out the registry URI, based on dev/staging scenario + chart_uri = f"oci://{registry}/{repository}" + if not helm_chart_path: + helm_chart_path = chart_uri + + if not custom_operator_version: + # most probably we are trying to install current operator which will be installed + # from OCI registry. The version (dev/staging) is set in `OPERATOR_VERSION` + custom_operator_version = os.environ.get("OPERATOR_VERSION") prepare_multi_cluster_namespaces( namespace, diff --git a/scripts/evergreen/e2e/single_e2e.sh b/scripts/evergreen/e2e/single_e2e.sh index 30effa4c1..8962f11c6 100755 --- a/scripts/evergreen/e2e/single_e2e.sh +++ b/scripts/evergreen/e2e/single_e2e.sh @@ -49,9 +49,9 @@ deploy_test_app() { BUILD_VARIANT="${BUILD_VARIANT:-default_build_variant}" chart_info=$(scripts/dev/run_python.sh scripts/release/oci_chart_info.py) - helm_oci_regisry=$(echo "$chart_info" | jq -r '.registry' ) - helm_oci_repository=$(echo "$chart_info" | jq -r '.repository' ) - helm_oci_registry_region=$(echo "$chart_info" | jq -r '.region' ) + helm_oci_regisry=$(echo "${chart_info}" | jq -r '.registry' ) + helm_oci_repository=$(echo "${chart_info}" | jq -r '.repository' ) + helm_oci_registry_region=$(echo "${chart_info}" | jq -r '.region' ) # note, that the 4 last parameters are used only for Mongodb resource testing - not for Ops Manager helm_params=( diff --git a/scripts/release/oci_chart_info.py b/scripts/release/oci_chart_info.py index 0e5b6bf54..c7c92ca71 100644 --- a/scripts/release/oci_chart_info.py +++ b/scripts/release/oci_chart_info.py @@ -1,11 +1,12 @@ +import json import os import sys -import json - from dataclasses import asdict + from lib.base_logger import logger from scripts.release.build.build_info import load_build_info + def main(): build_scenario = os.environ.get("BUILD_SCENARIO") build_info = load_build_info(build_scenario) @@ -15,7 +16,6 @@ def main(): print(j) - if __name__ == "__main__": try: main() From 4132fc6f7342fa23d6674a7958790df3b264d4b1 Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Thu, 16 Oct 2025 15:53:08 +0200 Subject: [PATCH 12/26] Add 0.0.0 while forming chart version --- docker/mongodb-kubernetes-tests/kubetester/operator.py | 3 ++- docker/mongodb-kubernetes-tests/tests/conftest.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docker/mongodb-kubernetes-tests/kubetester/operator.py b/docker/mongodb-kubernetes-tests/kubetester/operator.py index f75a321fb..87a0f7a4f 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/operator.py +++ b/docker/mongodb-kubernetes-tests/kubetester/operator.py @@ -66,7 +66,8 @@ def __init__( if not operator_version: # most probably we are trying to install current operator which will be installed # from OCI registry. The version (dev/staging) is set in `OPERATOR_VERSION` - operator_version = os.environ.get("OPERATOR_VERSION") + non_semver_operator_version = os.environ.get("OPERATOR_VERSION") + operator_version = f"0.0.0+{non_semver_operator_version}" if helm_args is None: helm_args = {} diff --git a/docker/mongodb-kubernetes-tests/tests/conftest.py b/docker/mongodb-kubernetes-tests/tests/conftest.py index cb46e4755..0fdf7f405 100644 --- a/docker/mongodb-kubernetes-tests/tests/conftest.py +++ b/docker/mongodb-kubernetes-tests/tests/conftest.py @@ -856,7 +856,8 @@ def _install_multi_cluster_operator( if not custom_operator_version: # most probably we are trying to install current operator which will be installed # from OCI registry. The version (dev/staging) is set in `OPERATOR_VERSION` - custom_operator_version = os.environ.get("OPERATOR_VERSION") + non_semver_custom_operator_version = os.environ.get("OPERATOR_VERSION") + custom_operator_version = f"0.0.0+{non_semver_custom_operator_version}" prepare_multi_cluster_namespaces( namespace, From 82bf02e02980de430309e8f66c18c12ddd9bb725 Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Thu, 16 Oct 2025 19:08:56 +0200 Subject: [PATCH 13/26] Fix `e2e_meko_mck_upgrade` by using OCI version only when version is not provided and chart is not meko or mck --- .evergreen.yml | 2 ++ docker/mongodb-kubernetes-tests/kubetester/operator.py | 5 ++++- docker/mongodb-kubernetes-tests/tests/conftest.py | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.evergreen.yml b/.evergreen.yml index ba802f58f..24cb7e071 100644 --- a/.evergreen.yml +++ b/.evergreen.yml @@ -37,6 +37,8 @@ variables: variant: init_test_run - name: build_init_om_images_ubi variant: init_test_run + - name: publish_helm_chart + variant: init_test_run - &base_no_om_image_dependency depends_on: diff --git a/docker/mongodb-kubernetes-tests/kubetester/operator.py b/docker/mongodb-kubernetes-tests/kubetester/operator.py index 87a0f7a4f..44a417dc2 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/operator.py +++ b/docker/mongodb-kubernetes-tests/kubetester/operator.py @@ -51,6 +51,9 @@ def __init__( api_client: Optional[client.api_client.ApiClient] = None, operator_version: Optional[str] = None, ): + # The Operator will be installed from the following repo, so adding it first + helm_repo_add("mongodb", "https://mongodb.github.io/helm-charts") + if not helm_chart_path: # login to the OCI container registry registry, repository, region = oci_chart_info() @@ -63,7 +66,7 @@ def __init__( chart_uri = f"oci://{registry}/{repository}" helm_chart_path = chart_uri - if not operator_version: + if not operator_version and helm_chart_path not in ("mongodb/mongodb-kubernetes", "mongodb/enterprise-operator"): # most probably we are trying to install current operator which will be installed # from OCI registry. The version (dev/staging) is set in `OPERATOR_VERSION` non_semver_operator_version = os.environ.get("OPERATOR_VERSION") diff --git a/docker/mongodb-kubernetes-tests/tests/conftest.py b/docker/mongodb-kubernetes-tests/tests/conftest.py index 0fdf7f405..c9242b84d 100644 --- a/docker/mongodb-kubernetes-tests/tests/conftest.py +++ b/docker/mongodb-kubernetes-tests/tests/conftest.py @@ -839,7 +839,7 @@ def _install_multi_cluster_operator( multi_cluster_operator_installation_config.update(helm_opts) # The Operator will be installed from the following repo, so adding it first - # helm_repo_add("mongodb", "https://mongodb.github.io/helm-charts") + helm_repo_add("mongodb", "https://mongodb.github.io/helm-charts") # login to the OCI container registry registry, repository, region = oci_chart_info() @@ -853,7 +853,7 @@ def _install_multi_cluster_operator( if not helm_chart_path: helm_chart_path = chart_uri - if not custom_operator_version: + if not custom_operator_version and helm_chart_path not in (MCK_HELM_CHART, LEGACY_OPERATOR_CHART): # most probably we are trying to install current operator which will be installed # from OCI registry. The version (dev/staging) is set in `OPERATOR_VERSION` non_semver_custom_operator_version = os.environ.get("OPERATOR_VERSION") From 6e641ce6e6c13613e6165c2848b0fd2fecc359ff Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Thu, 16 Oct 2025 19:10:25 +0200 Subject: [PATCH 14/26] Run precommit --- docker/mongodb-kubernetes-tests/kubetester/operator.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docker/mongodb-kubernetes-tests/kubetester/operator.py b/docker/mongodb-kubernetes-tests/kubetester/operator.py index 44a417dc2..955ef91da 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/operator.py +++ b/docker/mongodb-kubernetes-tests/kubetester/operator.py @@ -66,7 +66,10 @@ def __init__( chart_uri = f"oci://{registry}/{repository}" helm_chart_path = chart_uri - if not operator_version and helm_chart_path not in ("mongodb/mongodb-kubernetes", "mongodb/enterprise-operator"): + if not operator_version and helm_chart_path not in ( + "mongodb/mongodb-kubernetes", + "mongodb/enterprise-operator", + ): # most probably we are trying to install current operator which will be installed # from OCI registry. The version (dev/staging) is set in `OPERATOR_VERSION` non_semver_operator_version = os.environ.get("OPERATOR_VERSION") From e96e180ed0cde3c237bc0a11109be867cce89bea Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Thu, 16 Oct 2025 21:04:56 +0200 Subject: [PATCH 15/26] Fix CRDs not found issue by installing CRD from correct path --- docker/mongodb-kubernetes-tests/kubetester/helm.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/mongodb-kubernetes-tests/kubetester/helm.py b/docker/mongodb-kubernetes-tests/kubetester/helm.py index 40533b2b6..87ef8001b 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/helm.py +++ b/docker/mongodb-kubernetes-tests/kubetester/helm.py @@ -211,7 +211,8 @@ def helm_upgrade( chart_dir = helm_chart_path if helm_override_path else _helm_chart_dir(helm_chart_path) if apply_crds_first: - apply_crds_from_chart(chart_dir) + local_helm_chart_dir = "helm_chart" + apply_crds_from_chart(local_helm_chart_dir) command_args = _create_helm_args(helm_args, helm_options) args = [ From 93f3e12b1d08235599af292f0da4373f57d5c3cc Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Fri, 17 Oct 2025 15:47:34 +0200 Subject: [PATCH 16/26] Refactor a little, make consts etc --- .../kubetester/consts.py | 8 +++++ .../kubetester/helm.py | 24 +++++++++----- .../kubetester/operator.py | 17 +++++++--- .../tests/conftest.py | 33 ++++++++++--------- 4 files changed, 53 insertions(+), 29 deletions(-) create mode 100644 docker/mongodb-kubernetes-tests/kubetester/consts.py diff --git a/docker/mongodb-kubernetes-tests/kubetester/consts.py b/docker/mongodb-kubernetes-tests/kubetester/consts.py new file mode 100644 index 000000000..0728c7905 --- /dev/null +++ b/docker/mongodb-kubernetes-tests/kubetester/consts.py @@ -0,0 +1,8 @@ +OPERATOR_VERSION_ENV_VAR_NAME = "OPERATOR_VERSION" + +OCI_HELM_REGISTRY_ENV_VAR_NAME = "OCI_HELM_REGISTRY" +OCI_HELM_REPOSITORY_ENV_VAR_NAME = "OCI_HELM_REPOSITORY" +OCI_HELM_REGION_ENV_VAR_NAME = "OCI_HELM_REGION" + +LEGACY_OPERATOR_CHART = "mongodb/enterprise-operator" +MCK_HELM_CHART = "mongodb/mongodb-kubernetes" diff --git a/docker/mongodb-kubernetes-tests/kubetester/helm.py b/docker/mongodb-kubernetes-tests/kubetester/helm.py index 87ef8001b..d7050b0ab 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/helm.py +++ b/docker/mongodb-kubernetes-tests/kubetester/helm.py @@ -6,10 +6,14 @@ import uuid from typing import Dict, List, Optional, Tuple +from kubetester.consts import * from tests import test_logger logger = test_logger.get_test_logger(__name__) +# LOCAL_CRDs_DIR is the dir where local helm chart's CRDs are copied in tests image +LOCAL_CRDs_DIR = "helm_chart/crds" + def helm_template( helm_args: Dict, @@ -211,8 +215,7 @@ def helm_upgrade( chart_dir = helm_chart_path if helm_override_path else _helm_chart_dir(helm_chart_path) if apply_crds_first: - local_helm_chart_dir = "helm_chart" - apply_crds_from_chart(local_helm_chart_dir) + apply_crds_from_chart(LOCAL_CRDs_DIR) command_args = _create_helm_args(helm_args, helm_options) args = [ @@ -233,21 +236,24 @@ def helm_upgrade( process_run_and_check(command, check=True, capture_output=True, shell=True) +# oci_chart_info returns the respective registry/repo and region information +# based on the build scenario (dev/staging) tests are being run in. These are +# read from build_info.json and then set to the tests image as env vars. def oci_chart_info(): - registry = os.environ.get("OCI_HELM_REGISTRY") - repository = os.environ.get("OCI_HELM_REPOSITORY") - region = os.environ.get("OCI_HELM_REGION") + registry = os.environ.get(OCI_HELM_REGISTRY_ENV_VAR_NAME) + repository = os.environ.get(OCI_HELM_REPOSITORY_ENV_VAR_NAME) + region = os.environ.get(OCI_HELM_REGION_ENV_VAR_NAME) - print(f"oci chart details in test image is registry {registry}, repo {repository}, region {region}") + logger.info(f"oci chart details in test image is registry {registry}, repo {repository}, region {region}") return registry, f"{repository}/mongodb-kubernetes", region -def apply_crds_from_chart(chart_dir: str): - crd_files = glob.glob(os.path.join(chart_dir, "crds", "*.yaml")) +def apply_crds_from_chart(crds_dir: str): + crd_files = glob.glob(os.path.join(crds_dir, "*.yaml")) if not crd_files: - raise Exception(f"No CRD files found in chart directory: {chart_dir}") + raise Exception(f"No CRD files found in chart directory: {crds_dir}") logger.info(f"Found {len(crd_files)} CRD files to apply:") diff --git a/docker/mongodb-kubernetes-tests/kubetester/operator.py b/docker/mongodb-kubernetes-tests/kubetester/operator.py index 955ef91da..a05261034 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/operator.py +++ b/docker/mongodb-kubernetes-tests/kubetester/operator.py @@ -10,6 +10,7 @@ from kubernetes.client import V1CustomResourceDefinition, V1Deployment, V1Pod from kubernetes.client.rest import ApiException from kubetester import wait_for_webhook +from kubetester.consts import * from kubetester.create_or_replace_from_yaml import create_or_replace_from_yaml from kubetester.helm import ( helm_install, @@ -28,6 +29,7 @@ "opsmanagers.mongodb.com", ) + logger = test_logger.get_test_logger(__name__) @@ -54,6 +56,8 @@ def __init__( # The Operator will be installed from the following repo, so adding it first helm_repo_add("mongodb", "https://mongodb.github.io/helm-charts") + # helm_chart_path not being passed would mean we are on evg env and would like to + # install helm chart from OCI registry. if not helm_chart_path: # login to the OCI container registry registry, repository, region = oci_chart_info() @@ -66,13 +70,16 @@ def __init__( chart_uri = f"oci://{registry}/{repository}" helm_chart_path = chart_uri + # if operator_version is not specified and we are not installing the MCK or MEKO chart + # it would mean we want to install OCI published helm chart. Figure out respective version, + # it is set in env var `OPERATOR_VERSION` based on build_scenario. if not operator_version and helm_chart_path not in ( - "mongodb/mongodb-kubernetes", - "mongodb/enterprise-operator", + MCK_HELM_CHART, + LEGACY_OPERATOR_CHART, ): - # most probably we are trying to install current operator which will be installed - # from OCI registry. The version (dev/staging) is set in `OPERATOR_VERSION` - non_semver_operator_version = os.environ.get("OPERATOR_VERSION") + non_semver_operator_version = os.environ.get(OPERATOR_VERSION_ENV_VAR_NAME) + # when we publish the helm chart we append `0.0.0+` in the chart version, details are + # here https://docs.google.com/document/d/1eJ8iKsI0libbpcJakGjxcPfbrTn8lmcZDbQH1UqMR_g/edit?tab=t.gg5ble8qlesq operator_version = f"0.0.0+{non_semver_operator_version}" if helm_args is None: diff --git a/docker/mongodb-kubernetes-tests/tests/conftest.py b/docker/mongodb-kubernetes-tests/tests/conftest.py index c9242b84d..311a76fc1 100644 --- a/docker/mongodb-kubernetes-tests/tests/conftest.py +++ b/docker/mongodb-kubernetes-tests/tests/conftest.py @@ -20,6 +20,7 @@ update_configmap, ) from kubetester.awss3client import AwsS3Client +from kubetester.consts import * from kubetester.helm import ( helm_install_from_chart, helm_repo_add, @@ -60,9 +61,6 @@ LEGACY_CENTRAL_CLUSTER_NAME: str = "__default" LEGACY_DEPLOYMENT_STATE_VERSION: str = "1.27.0" -# Helm charts -LEGACY_OPERATOR_CHART = "mongodb/enterprise-operator" -MCK_HELM_CHART = "mongodb/mongodb-kubernetes" LOCAL_HELM_CHART_DIR = "helm_chart" OFFICIAL_OPERATOR_IMAGE_NAME = "mongodb-kubernetes" @@ -841,22 +839,27 @@ def _install_multi_cluster_operator( # The Operator will be installed from the following repo, so adding it first helm_repo_add("mongodb", "https://mongodb.github.io/helm-charts") - # login to the OCI container registry - registry, repository, region = oci_chart_info() - try: - oci_helm_registry_login(registry, region) - except Exception as e: - raise e - - # figure out the registry URI, based on dev/staging scenario - chart_uri = f"oci://{registry}/{repository}" + # helm_chart_path not being passed would mean we are on evg env and would like to + # install helm chart from OCI registry. if not helm_chart_path: + # login to the OCI container registry + registry, repository, region = oci_chart_info() + try: + oci_helm_registry_login(registry, region) + except Exception as e: + raise e + + # figure out the registry URI, based on dev/staging scenario + chart_uri = f"oci://{registry}/{repository}" + helm_chart_path = chart_uri if not custom_operator_version and helm_chart_path not in (MCK_HELM_CHART, LEGACY_OPERATOR_CHART): - # most probably we are trying to install current operator which will be installed - # from OCI registry. The version (dev/staging) is set in `OPERATOR_VERSION` - non_semver_custom_operator_version = os.environ.get("OPERATOR_VERSION") + # custom_operator_version is not set and chart is also neither MCK nor MEKO would mean we are trying to install + # the operator from OCI registry. The version based on build scenario (dev/staging) is set in `OPERATOR_VERSION` env var. + non_semver_custom_operator_version = os.environ.get(OPERATOR_VERSION_ENV_VAR_NAME) + # when we publish the helm chart we append `0.0.0+` in the chart version, details are + # here https://docs.google.com/document/d/1eJ8iKsI0libbpcJakGjxcPfbrTn8lmcZDbQH1UqMR_g/edit?tab=t.gg5ble8qlesq custom_operator_version = f"0.0.0+{non_semver_custom_operator_version}" prepare_multi_cluster_namespaces( From eb65be504e3659093a2adc9d6a4bdfba95b7dbf9 Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Wed, 22 Oct 2025 17:18:33 +0200 Subject: [PATCH 17/26] Make sure local e2es use local helm chart --- .../kubetester/helm.py | 42 +++++++++++++++++++ .../kubetester/operator.py | 27 +----------- .../tests/conftest.py | 24 +---------- 3 files changed, 46 insertions(+), 47 deletions(-) diff --git a/docker/mongodb-kubernetes-tests/kubetester/helm.py b/docker/mongodb-kubernetes-tests/kubetester/helm.py index d7050b0ab..23ca81823 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/helm.py +++ b/docker/mongodb-kubernetes-tests/kubetester/helm.py @@ -300,3 +300,45 @@ def _create_helm_args(helm_args: Dict[str, str], helm_options: Optional[List[str def _helm_chart_dir(default: Optional[str] = "helm_chart") -> str: return os.environ.get("HELM_CHART_DIR", default) + + +# helm_chart_path_and_version returns the chart path and version that we would like to install to run the E2E tests. +# for local tests it returns early with local helm chart dir and for other scenarios it figure out the chart and version +# based on the caller. In most of the cases we will install chart from OCI registry but for the tests where we would like +# to install MEKO's specific version or MCK's specific version, we would expec `helm_chart_path` to set already. +def helm_chart_path_and_version(helm_chart_path: str, operator_version: str) -> tuple[str, str]: + # these are imported here to resolve import cycle issue + from tests.conftest import local_operator + from tests.conftest import LOCAL_HELM_CHART_DIR + + if local_operator(): + return LOCAL_HELM_CHART_DIR, "" + + # if operator_version is not specified and we are not installing the MCK or MEKO chart + # it would mean we want to install OCI published helm chart. Figure out respective version, + # it is set in env var `OPERATOR_VERSION` based on build_scenario. + if not operator_version and helm_chart_path not in ( + MCK_HELM_CHART, + LEGACY_OPERATOR_CHART, + ): + non_semver_operator_version = os.environ.get(OPERATOR_VERSION_ENV_VAR_NAME) + # when we publish the helm chart we append `0.0.0+` in the chart version, details are + # here https://docs.google.com/document/d/1eJ8iKsI0libbpcJakGjxcPfbrTn8lmcZDbQH1UqMR_g/edit?tab=t.gg5ble8qlesq + operator_version = f"0.0.0+{non_semver_operator_version}" + + + # helm_chart_path not being passed would mean we are on evg env and would like to + # install helm chart from OCI registry. + if not helm_chart_path: + # login to the OCI container registry + registry, repository, region = oci_chart_info() + try: + oci_helm_registry_login(registry, region) + except Exception as e: + raise e + + # figure out the registry URI, based on dev/staging scenario + chart_uri = f"oci://{registry}/{repository}" + helm_chart_path = chart_uri + + return helm_chart_path, operator_version diff --git a/docker/mongodb-kubernetes-tests/kubetester/operator.py b/docker/mongodb-kubernetes-tests/kubetester/operator.py index a05261034..b4ea350f0 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/operator.py +++ b/docker/mongodb-kubernetes-tests/kubetester/operator.py @@ -20,6 +20,7 @@ helm_upgrade, oci_chart_info, oci_helm_registry_login, + helm_chart_path_and_version, ) from tests import test_logger @@ -56,31 +57,7 @@ def __init__( # The Operator will be installed from the following repo, so adding it first helm_repo_add("mongodb", "https://mongodb.github.io/helm-charts") - # helm_chart_path not being passed would mean we are on evg env and would like to - # install helm chart from OCI registry. - if not helm_chart_path: - # login to the OCI container registry - registry, repository, region = oci_chart_info() - try: - oci_helm_registry_login(registry, region) - except Exception as e: - raise e - - # figure out the registry URI, based on dev/staging scenario - chart_uri = f"oci://{registry}/{repository}" - helm_chart_path = chart_uri - - # if operator_version is not specified and we are not installing the MCK or MEKO chart - # it would mean we want to install OCI published helm chart. Figure out respective version, - # it is set in env var `OPERATOR_VERSION` based on build_scenario. - if not operator_version and helm_chart_path not in ( - MCK_HELM_CHART, - LEGACY_OPERATOR_CHART, - ): - non_semver_operator_version = os.environ.get(OPERATOR_VERSION_ENV_VAR_NAME) - # when we publish the helm chart we append `0.0.0+` in the chart version, details are - # here https://docs.google.com/document/d/1eJ8iKsI0libbpcJakGjxcPfbrTn8lmcZDbQH1UqMR_g/edit?tab=t.gg5ble8qlesq - operator_version = f"0.0.0+{non_semver_operator_version}" + helm_chart_path, operator_version = helm_chart_path_and_version(helm_chart_path, operator_version) if helm_args is None: helm_args = {} diff --git a/docker/mongodb-kubernetes-tests/tests/conftest.py b/docker/mongodb-kubernetes-tests/tests/conftest.py index 311a76fc1..edcef1e73 100644 --- a/docker/mongodb-kubernetes-tests/tests/conftest.py +++ b/docker/mongodb-kubernetes-tests/tests/conftest.py @@ -26,6 +26,7 @@ helm_repo_add, oci_chart_info, oci_helm_registry_login, + helm_chart_path_and_version, ) from kubetester.kubetester import KubernetesTester from kubetester.kubetester import fixture as _fixture @@ -839,28 +840,7 @@ def _install_multi_cluster_operator( # The Operator will be installed from the following repo, so adding it first helm_repo_add("mongodb", "https://mongodb.github.io/helm-charts") - # helm_chart_path not being passed would mean we are on evg env and would like to - # install helm chart from OCI registry. - if not helm_chart_path: - # login to the OCI container registry - registry, repository, region = oci_chart_info() - try: - oci_helm_registry_login(registry, region) - except Exception as e: - raise e - - # figure out the registry URI, based on dev/staging scenario - chart_uri = f"oci://{registry}/{repository}" - - helm_chart_path = chart_uri - - if not custom_operator_version and helm_chart_path not in (MCK_HELM_CHART, LEGACY_OPERATOR_CHART): - # custom_operator_version is not set and chart is also neither MCK nor MEKO would mean we are trying to install - # the operator from OCI registry. The version based on build scenario (dev/staging) is set in `OPERATOR_VERSION` env var. - non_semver_custom_operator_version = os.environ.get(OPERATOR_VERSION_ENV_VAR_NAME) - # when we publish the helm chart we append `0.0.0+` in the chart version, details are - # here https://docs.google.com/document/d/1eJ8iKsI0libbpcJakGjxcPfbrTn8lmcZDbQH1UqMR_g/edit?tab=t.gg5ble8qlesq - custom_operator_version = f"0.0.0+{non_semver_custom_operator_version}" + helm_chart_path, custom_operator_version = helm_chart_path_and_version(helm_chart_path, custom_operator_version) prepare_multi_cluster_namespaces( namespace, From 5cb41a098e9eddc46d2a1e31bb17b26411d58f17 Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Wed, 22 Oct 2025 17:19:26 +0200 Subject: [PATCH 18/26] Run precommit --- docker/mongodb-kubernetes-tests/kubetester/helm.py | 6 ++---- docker/mongodb-kubernetes-tests/kubetester/operator.py | 4 ++-- docker/mongodb-kubernetes-tests/tests/conftest.py | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/docker/mongodb-kubernetes-tests/kubetester/helm.py b/docker/mongodb-kubernetes-tests/kubetester/helm.py index 23ca81823..9990117e0 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/helm.py +++ b/docker/mongodb-kubernetes-tests/kubetester/helm.py @@ -308,12 +308,11 @@ def _helm_chart_dir(default: Optional[str] = "helm_chart") -> str: # to install MEKO's specific version or MCK's specific version, we would expec `helm_chart_path` to set already. def helm_chart_path_and_version(helm_chart_path: str, operator_version: str) -> tuple[str, str]: # these are imported here to resolve import cycle issue - from tests.conftest import local_operator - from tests.conftest import LOCAL_HELM_CHART_DIR + from tests.conftest import LOCAL_HELM_CHART_DIR, local_operator if local_operator(): return LOCAL_HELM_CHART_DIR, "" - + # if operator_version is not specified and we are not installing the MCK or MEKO chart # it would mean we want to install OCI published helm chart. Figure out respective version, # it is set in env var `OPERATOR_VERSION` based on build_scenario. @@ -326,7 +325,6 @@ def helm_chart_path_and_version(helm_chart_path: str, operator_version: str) -> # here https://docs.google.com/document/d/1eJ8iKsI0libbpcJakGjxcPfbrTn8lmcZDbQH1UqMR_g/edit?tab=t.gg5ble8qlesq operator_version = f"0.0.0+{non_semver_operator_version}" - # helm_chart_path not being passed would mean we are on evg env and would like to # install helm chart from OCI registry. if not helm_chart_path: diff --git a/docker/mongodb-kubernetes-tests/kubetester/operator.py b/docker/mongodb-kubernetes-tests/kubetester/operator.py index b4ea350f0..c7462e6d4 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/operator.py +++ b/docker/mongodb-kubernetes-tests/kubetester/operator.py @@ -13,6 +13,7 @@ from kubetester.consts import * from kubetester.create_or_replace_from_yaml import create_or_replace_from_yaml from kubetester.helm import ( + helm_chart_path_and_version, helm_install, helm_repo_add, helm_template, @@ -20,7 +21,6 @@ helm_upgrade, oci_chart_info, oci_helm_registry_login, - helm_chart_path_and_version, ) from tests import test_logger @@ -57,7 +57,7 @@ def __init__( # The Operator will be installed from the following repo, so adding it first helm_repo_add("mongodb", "https://mongodb.github.io/helm-charts") - helm_chart_path, operator_version = helm_chart_path_and_version(helm_chart_path, operator_version) + helm_chart_path, operator_version = helm_chart_path_and_version(helm_chart_path, operator_version) if helm_args is None: helm_args = {} diff --git a/docker/mongodb-kubernetes-tests/tests/conftest.py b/docker/mongodb-kubernetes-tests/tests/conftest.py index edcef1e73..d3223c145 100644 --- a/docker/mongodb-kubernetes-tests/tests/conftest.py +++ b/docker/mongodb-kubernetes-tests/tests/conftest.py @@ -22,11 +22,11 @@ from kubetester.awss3client import AwsS3Client from kubetester.consts import * from kubetester.helm import ( + helm_chart_path_and_version, helm_install_from_chart, helm_repo_add, oci_chart_info, oci_helm_registry_login, - helm_chart_path_and_version, ) from kubetester.kubetester import KubernetesTester from kubetester.kubetester import fixture as _fixture From 106851878b8eca79a125ec0f1d8425dc3f70ef4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kara=C5=9B?= Date: Tue, 28 Oct 2025 12:27:58 +0100 Subject: [PATCH 19/26] Review fixes --- docker/mongodb-kubernetes-tests/Dockerfile | 15 ++++------ .../kubetester/helm.py | 19 ++++++------ .../kubetester/operator.py | 5 ---- .../tests/conftest.py | 6 +--- scripts/evergreen/e2e/single_e2e.sh | 24 ++++----------- scripts/release/oci_chart_info.py | 30 +++++++++++++++---- 6 files changed, 47 insertions(+), 52 deletions(-) diff --git a/docker/mongodb-kubernetes-tests/Dockerfile b/docker/mongodb-kubernetes-tests/Dockerfile index b91ef0516..b6dc2e0b0 100644 --- a/docker/mongodb-kubernetes-tests/Dockerfile +++ b/docker/mongodb-kubernetes-tests/Dockerfile @@ -16,7 +16,11 @@ RUN apt-get -qq update \ COPY requirements.txt requirements.txt -RUN python3 -m venv /venv && . /venv/bin/activate && pip install --upgrade pip && GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1 pip install -r requirements.txt +RUN python3 -m venv /venv \ + && . /venv/bin/activate \ + && pip install --upgrade pip \ + && GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1 pip install -r requirements.txt \ + && pip install awscli # install aws, required to run helm registry login while running the tests FROM scratch AS tools_downloader @@ -44,9 +48,7 @@ RUN apt-get -qq update \ curl \ libldap2-dev \ libsasl2-dev \ - git \ - openssl \ - unzip + git RUN mkdir -p /tmp/mongodb-tools && \ tar xfz /tmp/mongodb-tools.tgz -C /tmp/mongodb-tools && \ @@ -67,11 +69,6 @@ RUN curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl - && chmod +x ./kubectl \ && mv ./kubectl /usr/local/bin/kubectl -# install aws, required to run helm registry login while running the tests -RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \ - && unzip -q awscliv2.zip \ - && ./aws/install - COPY --from=builder /venv /venv ENV PATH="/venv/bin:${PATH}" diff --git a/docker/mongodb-kubernetes-tests/kubetester/helm.py b/docker/mongodb-kubernetes-tests/kubetester/helm.py index 9990117e0..0374f4315 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/helm.py +++ b/docker/mongodb-kubernetes-tests/kubetester/helm.py @@ -149,7 +149,7 @@ def process_run_and_check(args, **kwargs): raise -def oci_helm_registry_login(helm_registry: str, region: str): +def helm_registry_login_to_ecr(helm_registry: str, region: str): logger.info(f"Attempting to log into ECR registry: {helm_registry}, using helm registry login.") aws_command = ["aws", "ecr", "get-login-password", "--region", region] @@ -303,9 +303,9 @@ def _helm_chart_dir(default: Optional[str] = "helm_chart") -> str: # helm_chart_path_and_version returns the chart path and version that we would like to install to run the E2E tests. -# for local tests it returns early with local helm chart dir and for other scenarios it figure out the chart and version +# for local tests it returns early with local helm chart dir and for other scenarios it figures out the chart and version # based on the caller. In most of the cases we will install chart from OCI registry but for the tests where we would like -# to install MEKO's specific version or MCK's specific version, we would expec `helm_chart_path` to set already. +# to install MEKO's specific version or MCK's specific version, we would expect `helm_chart_path` to set already. def helm_chart_path_and_version(helm_chart_path: str, operator_version: str) -> tuple[str, str]: # these are imported here to resolve import cycle issue from tests.conftest import LOCAL_HELM_CHART_DIR, local_operator @@ -313,7 +313,7 @@ def helm_chart_path_and_version(helm_chart_path: str, operator_version: str) -> if local_operator(): return LOCAL_HELM_CHART_DIR, "" - # if operator_version is not specified and we are not installing the MCK or MEKO chart + # if operator_version is not specified, and we are not installing the MCK or MEKO chart # it would mean we want to install OCI published helm chart. Figure out respective version, # it is set in env var `OPERATOR_VERSION` based on build_scenario. if not operator_version and helm_chart_path not in ( @@ -328,12 +328,13 @@ def helm_chart_path_and_version(helm_chart_path: str, operator_version: str) -> # helm_chart_path not being passed would mean we are on evg env and would like to # install helm chart from OCI registry. if not helm_chart_path: - # login to the OCI container registry registry, repository, region = oci_chart_info() - try: - oci_helm_registry_login(registry, region) - except Exception as e: - raise e + # If ECR we need to login first to the OCI container registry + if registry == "268558157000.dkr.ecr.us-east-1.amazonaws.com": + try: + helm_registry_login_to_ecr(registry, region) + except Exception as e: + raise Exception(f"Failed to login to ECR helm registry {registry}. Error: {e}") # figure out the registry URI, based on dev/staging scenario chart_uri = f"oci://{registry}/{repository}" diff --git a/docker/mongodb-kubernetes-tests/kubetester/operator.py b/docker/mongodb-kubernetes-tests/kubetester/operator.py index c7462e6d4..27d0f4041 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/operator.py +++ b/docker/mongodb-kubernetes-tests/kubetester/operator.py @@ -1,7 +1,5 @@ from __future__ import annotations -import logging -import os import time from typing import Dict, List, Optional @@ -10,7 +8,6 @@ from kubernetes.client import V1CustomResourceDefinition, V1Deployment, V1Pod from kubernetes.client.rest import ApiException from kubetester import wait_for_webhook -from kubetester.consts import * from kubetester.create_or_replace_from_yaml import create_or_replace_from_yaml from kubetester.helm import ( helm_chart_path_and_version, @@ -19,8 +16,6 @@ helm_template, helm_uninstall, helm_upgrade, - oci_chart_info, - oci_helm_registry_login, ) from tests import test_logger diff --git a/docker/mongodb-kubernetes-tests/tests/conftest.py b/docker/mongodb-kubernetes-tests/tests/conftest.py index d3223c145..2269e5925 100644 --- a/docker/mongodb-kubernetes-tests/tests/conftest.py +++ b/docker/mongodb-kubernetes-tests/tests/conftest.py @@ -22,11 +22,8 @@ from kubetester.awss3client import AwsS3Client from kubetester.consts import * from kubetester.helm import ( - helm_chart_path_and_version, helm_install_from_chart, helm_repo_add, - oci_chart_info, - oci_helm_registry_login, ) from kubetester.kubetester import KubernetesTester from kubetester.kubetester import fixture as _fixture @@ -840,8 +837,6 @@ def _install_multi_cluster_operator( # The Operator will be installed from the following repo, so adding it first helm_repo_add("mongodb", "https://mongodb.github.io/helm-charts") - helm_chart_path, custom_operator_version = helm_chart_path_and_version(helm_chart_path, custom_operator_version) - prepare_multi_cluster_namespaces( namespace, multi_cluster_operator_installation_config, @@ -857,6 +852,7 @@ def _install_multi_cluster_operator( helm_args=multi_cluster_operator_installation_config, api_client=central_cluster_client, helm_chart_path=helm_chart_path, + operator_version=custom_operator_version, ).upgrade(multi_cluster=True, custom_operator_version=custom_operator_version, apply_crds_first=apply_crds_first) # If we're running locally, then immediately after installing the deployment, we scale it to zero. diff --git a/scripts/evergreen/e2e/single_e2e.sh b/scripts/evergreen/e2e/single_e2e.sh index 8962f11c6..32ab7a59c 100755 --- a/scripts/evergreen/e2e/single_e2e.sh +++ b/scripts/evergreen/e2e/single_e2e.sh @@ -48,14 +48,15 @@ deploy_test_app() { BUILD_ID="${BUILD_ID:-default_build_id}" BUILD_VARIANT="${BUILD_VARIANT:-default_build_variant}" - chart_info=$(scripts/dev/run_python.sh scripts/release/oci_chart_info.py) - helm_oci_regisry=$(echo "${chart_info}" | jq -r '.registry' ) + chart_info=$(scripts/dev/run_python.sh scripts/release/oci_chart_info.py --build_scenario "${BUILD_SCENARIO}") + helm_oci_registry=$(echo "${chart_info}" | jq -r '.registry' ) helm_oci_repository=$(echo "${chart_info}" | jq -r '.repository' ) helm_oci_registry_region=$(echo "${chart_info}" | jq -r '.region' ) # note, that the 4 last parameters are used only for Mongodb resource testing - not for Ops Manager helm_params=( "--set" "taskId=${task_id:-'not-specified'}" + "--set" "operator.version=${OPERATOR_VERSION}" "--set" "namespace=${NAMESPACE}" "--set" "taskName=${task_name}" "--set" "mekoTestsRegistry=${MEKO_TESTS_REGISTRY}" @@ -81,6 +82,9 @@ deploy_test_app() { "--set" "cognito_user_password=${cognito_user_password}" "--set" "cognito_workload_url=${cognito_workload_url}" "--set" "cognito_workload_user_id=${cognito_workload_user_id}" + "--set" "helm.oci.registry=${helm_oci_registry}" + "--set" "helm.oci.repository=${helm_oci_repository}" + "--set" "helm.oci.region=${helm_oci_registry_region}" ) # shellcheck disable=SC2154 @@ -147,22 +151,6 @@ deploy_test_app() { helm_params+=("--set" "omDebugHttp=true") fi - if [[ -n "${helm_oci_regisry:-}" ]]; then - helm_params+=("--set" "helm.oci.registry=${helm_oci_regisry}") - fi - - if [[ -n "${helm_oci_repository:-}" ]]; then - helm_params+=("--set" "helm.oci.repository=${helm_oci_repository}") - fi - - if [[ -n "${helm_oci_registry_region:-}" ]]; then - helm_params+=("--set" "helm.oci.region=${helm_oci_registry_region}") - fi - - if [[ -n "${OPERATOR_VERSION:-}" ]]; then - helm_params+=("--set" "operator.version=${OPERATOR_VERSION}") - fi - helm_params+=("--set" "opsManagerVersion=${ops_manager_version}") helm template "scripts/evergreen/deployments/test-app" "${helm_params[@]}" > "${helm_template_file}" || exit 1 diff --git a/scripts/release/oci_chart_info.py b/scripts/release/oci_chart_info.py index c7c92ca71..a6f100126 100644 --- a/scripts/release/oci_chart_info.py +++ b/scripts/release/oci_chart_info.py @@ -1,14 +1,33 @@ +import argparse import json -import os -import sys from dataclasses import asdict -from lib.base_logger import logger +from release.build.build_scenario import BuildScenario + from scripts.release.build.build_info import load_build_info def main(): - build_scenario = os.environ.get("BUILD_SCENARIO") + supported_scenarios = list(BuildScenario) + + parser = argparse.ArgumentParser( + description="""Dump the Helm chart information for the 'mongodb-kubernetes' chart as JSON.""", + formatter_class=argparse.RawTextHelpFormatter, + ) + parser.add_argument( + "-b", + "--build-scenario", + metavar="", + action="store", + required=True, + type=str, + choices=supported_scenarios, + help=f"""Build scenario when reading configuration from 'build_info.json'. + Options: {", ".join(supported_scenarios)}. For '{BuildScenario.DEVELOPMENT}' the '{BuildScenario.PATCH}' scenario is used to read values from 'build_info.json'""", + ) + args = parser.parse_args() + + build_scenario = BuildScenario(args.build_scenario) build_info = load_build_info(build_scenario) chart_info = build_info.helm_charts["mongodb-kubernetes"] @@ -20,5 +39,4 @@ def main(): try: main() except Exception as e: - logger.error(f"Failed while dumping the chart_info as json. Error: {e}") - sys.exit(1) + raise Exception(f"Failed while dumping the chart_info as json. Error: {e}") From 829393f8bc228e9b9eabeb40fb3e0337b447ea2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kara=C5=9B?= Date: Tue, 28 Oct 2025 15:10:10 +0100 Subject: [PATCH 20/26] Fix tests --- docker/mongodb-kubernetes-tests/Dockerfile | 1 - scripts/evergreen/e2e/single_e2e.sh | 5 ++++- scripts/release/oci_chart_info.py | 3 +-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docker/mongodb-kubernetes-tests/Dockerfile b/docker/mongodb-kubernetes-tests/Dockerfile index b6dc2e0b0..8ce644cea 100644 --- a/docker/mongodb-kubernetes-tests/Dockerfile +++ b/docker/mongodb-kubernetes-tests/Dockerfile @@ -48,7 +48,6 @@ RUN apt-get -qq update \ curl \ libldap2-dev \ libsasl2-dev \ - git RUN mkdir -p /tmp/mongodb-tools && \ tar xfz /tmp/mongodb-tools.tgz -C /tmp/mongodb-tools && \ diff --git a/scripts/evergreen/e2e/single_e2e.sh b/scripts/evergreen/e2e/single_e2e.sh index 32ab7a59c..2814dca9a 100755 --- a/scripts/evergreen/e2e/single_e2e.sh +++ b/scripts/evergreen/e2e/single_e2e.sh @@ -48,7 +48,10 @@ deploy_test_app() { BUILD_ID="${BUILD_ID:-default_build_id}" BUILD_VARIANT="${BUILD_VARIANT:-default_build_variant}" - chart_info=$(scripts/dev/run_python.sh scripts/release/oci_chart_info.py --build_scenario "${BUILD_SCENARIO}") + if ! chart_info=$(scripts/dev/run_python.sh scripts/release/oci_chart_info.py --build-scenario "${BUILD_SCENARIO}" 2>&1); then + echo "${chart_info}" + exit 1 + fi helm_oci_registry=$(echo "${chart_info}" | jq -r '.registry' ) helm_oci_repository=$(echo "${chart_info}" | jq -r '.repository' ) helm_oci_registry_region=$(echo "${chart_info}" | jq -r '.region' ) diff --git a/scripts/release/oci_chart_info.py b/scripts/release/oci_chart_info.py index a6f100126..c1ad488fa 100644 --- a/scripts/release/oci_chart_info.py +++ b/scripts/release/oci_chart_info.py @@ -2,9 +2,8 @@ import json from dataclasses import asdict -from release.build.build_scenario import BuildScenario - from scripts.release.build.build_info import load_build_info +from scripts.release.build.build_scenario import BuildScenario def main(): From ca7881cb059a18ca61df713c3e25f7fb96d332a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kara=C5=9B?= Date: Tue, 28 Oct 2025 15:13:30 +0100 Subject: [PATCH 21/26] Fixes after merge with master --- scripts/release/oci_chart_info.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/release/oci_chart_info.py b/scripts/release/oci_chart_info.py index c1ad488fa..000cb5f75 100644 --- a/scripts/release/oci_chart_info.py +++ b/scripts/release/oci_chart_info.py @@ -2,13 +2,12 @@ import json from dataclasses import asdict +from scripts.release.argparse_utils import get_scenario_from_arg from scripts.release.build.build_info import load_build_info -from scripts.release.build.build_scenario import BuildScenario +from scripts.release.build.build_scenario import SUPPORTED_SCENARIOS, BuildScenario def main(): - supported_scenarios = list(BuildScenario) - parser = argparse.ArgumentParser( description="""Dump the Helm chart information for the 'mongodb-kubernetes' chart as JSON.""", formatter_class=argparse.RawTextHelpFormatter, @@ -20,13 +19,13 @@ def main(): action="store", required=True, type=str, - choices=supported_scenarios, + choices=SUPPORTED_SCENARIOS, help=f"""Build scenario when reading configuration from 'build_info.json'. - Options: {", ".join(supported_scenarios)}. For '{BuildScenario.DEVELOPMENT}' the '{BuildScenario.PATCH}' scenario is used to read values from 'build_info.json'""", + Options: {", ".join(SUPPORTED_SCENARIOS)}. For '{BuildScenario.DEVELOPMENT}' the '{BuildScenario.PATCH}' scenario is used to read values from 'build_info.json'""", ) args = parser.parse_args() - build_scenario = BuildScenario(args.build_scenario) + build_scenario = get_scenario_from_arg(args.build_scenario) build_info = load_build_info(build_scenario) chart_info = build_info.helm_charts["mongodb-kubernetes"] From 084b8f2ee8280921c4dd613ab0a5200a12457f22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kara=C5=9B?= Date: Tue, 28 Oct 2025 16:04:59 +0100 Subject: [PATCH 22/26] Add version_prefix to build_info.json + other fixes --- build_info.json | 2 ++ docker/mongodb-kubernetes-tests/Dockerfile | 5 ++++- .../kubetester/consts.py | 3 +-- .../kubetester/helm.py | 10 ++++----- .../deployments/test-app/values.yaml | 4 +--- scripts/evergreen/e2e/single_e2e.sh | 4 +++- scripts/release/build/build_info.py | 4 +++- scripts/release/publish_helm_chart.py | 22 +++++++++---------- scripts/release/tests/build_info_test.py | 8 ++++--- 9 files changed, 34 insertions(+), 28 deletions(-) diff --git a/build_info.json b/build_info.json index 3bc34cff2..f4d1c790d 100644 --- a/build_info.json +++ b/build_info.json @@ -383,12 +383,14 @@ "helm-charts": { "mongodb-kubernetes": { "patch": { + "version-prefix": "0.0.0+", "registry": "268558157000.dkr.ecr.us-east-1.amazonaws.com", "region": "us-east-1", "repository": "dev/mongodb/helm-charts" }, "staging": { "sign": true, + "version-prefix": "0.0.0+", "registry": "268558157000.dkr.ecr.us-east-1.amazonaws.com", "region": "us-east-1", "repository": "staging/mongodb/helm-charts" diff --git a/docker/mongodb-kubernetes-tests/Dockerfile b/docker/mongodb-kubernetes-tests/Dockerfile index 8ce644cea..b2ebf3cf9 100644 --- a/docker/mongodb-kubernetes-tests/Dockerfile +++ b/docker/mongodb-kubernetes-tests/Dockerfile @@ -16,11 +16,12 @@ RUN apt-get -qq update \ COPY requirements.txt requirements.txt +# install aws, required to run helm registry login while running the tests RUN python3 -m venv /venv \ && . /venv/bin/activate \ && pip install --upgrade pip \ && GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1 pip install -r requirements.txt \ - && pip install awscli # install aws, required to run helm registry login while running the tests + && pip install awscli FROM scratch AS tools_downloader @@ -48,6 +49,8 @@ RUN apt-get -qq update \ curl \ libldap2-dev \ libsasl2-dev \ + git \ + openssl RUN mkdir -p /tmp/mongodb-tools && \ tar xfz /tmp/mongodb-tools.tgz -C /tmp/mongodb-tools && \ diff --git a/docker/mongodb-kubernetes-tests/kubetester/consts.py b/docker/mongodb-kubernetes-tests/kubetester/consts.py index 0728c7905..20bed74c2 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/consts.py +++ b/docker/mongodb-kubernetes-tests/kubetester/consts.py @@ -1,5 +1,4 @@ -OPERATOR_VERSION_ENV_VAR_NAME = "OPERATOR_VERSION" - +OCI_HELM_VERSION = "OCI_HELM_VERSION" OCI_HELM_REGISTRY_ENV_VAR_NAME = "OCI_HELM_REGISTRY" OCI_HELM_REPOSITORY_ENV_VAR_NAME = "OCI_HELM_REPOSITORY" OCI_HELM_REGION_ENV_VAR_NAME = "OCI_HELM_REGION" diff --git a/docker/mongodb-kubernetes-tests/kubetester/helm.py b/docker/mongodb-kubernetes-tests/kubetester/helm.py index 0374f4315..e2ca8bda3 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/helm.py +++ b/docker/mongodb-kubernetes-tests/kubetester/helm.py @@ -13,6 +13,7 @@ # LOCAL_CRDs_DIR is the dir where local helm chart's CRDs are copied in tests image LOCAL_CRDs_DIR = "helm_chart/crds" +OCI_HELM_REGISTRY_ECR = "268558157000.dkr.ecr.us-east-1.amazonaws.com" def helm_template( @@ -314,15 +315,12 @@ def helm_chart_path_and_version(helm_chart_path: str, operator_version: str) -> return LOCAL_HELM_CHART_DIR, "" # if operator_version is not specified, and we are not installing the MCK or MEKO chart - # it would mean we want to install OCI published helm chart. Figure out respective version, - # it is set in env var `OPERATOR_VERSION` based on build_scenario. + # it would mean we want to install OCI published helm chart. if not operator_version and helm_chart_path not in ( MCK_HELM_CHART, LEGACY_OPERATOR_CHART, ): - non_semver_operator_version = os.environ.get(OPERATOR_VERSION_ENV_VAR_NAME) - # when we publish the helm chart we append `0.0.0+` in the chart version, details are - # here https://docs.google.com/document/d/1eJ8iKsI0libbpcJakGjxcPfbrTn8lmcZDbQH1UqMR_g/edit?tab=t.gg5ble8qlesq + non_semver_operator_version = os.environ.get(OCI_HELM_VERSION) operator_version = f"0.0.0+{non_semver_operator_version}" # helm_chart_path not being passed would mean we are on evg env and would like to @@ -330,7 +328,7 @@ def helm_chart_path_and_version(helm_chart_path: str, operator_version: str) -> if not helm_chart_path: registry, repository, region = oci_chart_info() # If ECR we need to login first to the OCI container registry - if registry == "268558157000.dkr.ecr.us-east-1.amazonaws.com": + if registry == OCI_HELM_REGISTRY_ECR: try: helm_registry_login_to_ecr(registry, region) except Exception as e: diff --git a/scripts/evergreen/deployments/test-app/values.yaml b/scripts/evergreen/deployments/test-app/values.yaml index 09ab966c7..579bc426b 100644 --- a/scripts/evergreen/deployments/test-app/values.yaml +++ b/scripts/evergreen/deployments/test-app/values.yaml @@ -48,9 +48,7 @@ omDebugHttp: # to run a test. helm: oci: + version: "" registry: "" repository: "" region: "" - -operator: - version: "" diff --git a/scripts/evergreen/e2e/single_e2e.sh b/scripts/evergreen/e2e/single_e2e.sh index 2814dca9a..7985483db 100755 --- a/scripts/evergreen/e2e/single_e2e.sh +++ b/scripts/evergreen/e2e/single_e2e.sh @@ -55,11 +55,12 @@ deploy_test_app() { helm_oci_registry=$(echo "${chart_info}" | jq -r '.registry' ) helm_oci_repository=$(echo "${chart_info}" | jq -r '.repository' ) helm_oci_registry_region=$(echo "${chart_info}" | jq -r '.region' ) + helm_oci_version_prefix=$(echo "${chart_info}" | jq -r '.version_prefix // empty' ) + helm_oci_version="${helm_oci_version_prefix:-}${OPERATOR_VERSION}" # note, that the 4 last parameters are used only for Mongodb resource testing - not for Ops Manager helm_params=( "--set" "taskId=${task_id:-'not-specified'}" - "--set" "operator.version=${OPERATOR_VERSION}" "--set" "namespace=${NAMESPACE}" "--set" "taskName=${task_name}" "--set" "mekoTestsRegistry=${MEKO_TESTS_REGISTRY}" @@ -85,6 +86,7 @@ deploy_test_app() { "--set" "cognito_user_password=${cognito_user_password}" "--set" "cognito_workload_url=${cognito_workload_url}" "--set" "cognito_workload_user_id=${cognito_workload_user_id}" + "--set" "helm.oci.version=${helm_oci_version}" "--set" "helm.oci.registry=${helm_oci_registry}" "--set" "helm.oci.repository=${helm_oci_repository}" "--set" "helm.oci.region=${helm_oci_registry_region}" diff --git a/scripts/release/build/build_info.py b/scripts/release/build/build_info.py index 45db5b290..cad4df09e 100644 --- a/scripts/release/build/build_info.py +++ b/scripts/release/build/build_info.py @@ -44,7 +44,8 @@ class BinaryInfo: class HelmChartInfo: repository: str registry: str - region: str + region: str = None + version_prefix: str = None sign: bool = False @@ -112,6 +113,7 @@ def load_build_info(scenario: BuildScenario) -> BuildInfo: helm_charts[name] = HelmChartInfo( repository=scenario_data.get("repository"), sign=scenario_data.get("sign", False), + version_prefix=scenario_data.get("version-prefix"), registry=scenario_data.get("registry"), region=scenario_data.get("region") ) diff --git a/scripts/release/publish_helm_chart.py b/scripts/release/publish_helm_chart.py index cae99b19e..2593e0eb9 100644 --- a/scripts/release/publish_helm_chart.py +++ b/scripts/release/publish_helm_chart.py @@ -1,7 +1,6 @@ import argparse import os import subprocess -import sys import yaml @@ -28,7 +27,7 @@ def run_command(command: list[str]): # update_chart_and_get_metadata updates the helm chart's Chart.yaml and sets the version # to either evg patch id or commit which is set in OPERATOR_VERSION. -def update_chart_and_get_metadata(chart_dir: str, build_scenario) -> tuple[str, str]: +def update_chart_and_get_metadata(chart_dir: str, version_prefix: str = None) -> tuple[str, str]: chart_path = os.path.join(chart_dir, "Chart.yaml") version = os.environ.get("OPERATOR_VERSION") if not version: @@ -50,13 +49,15 @@ def update_chart_and_get_metadata(chart_dir: str, build_scenario) -> tuple[str, if not chart_name: raise ValueError("Chart.yaml is missing required 'name' field.") except Exception as e: - raise Exception(f"Unable to load Chart.yaml from dir {chart_path}") + raise Exception(f"Unable to load Chart.yaml from dir {chart_path}: {e}") - # if build_scenario is release, the chart.yaml would already have correct chart version - if build_scenario == BuildScenario.RELEASE: + # If version_prefix is not specified, the chart.yaml would already have correct chart version + if version_prefix is None: return chart_name, version - new_version = f"0.0.0+{version}" + # When we publish the helm chart to dev and staging we append `0.0.0+` in the chart version, details are + # here https://docs.google.com/document/d/1eJ8iKsI0libbpcJakGjxcPfbrTn8lmcZDbQH1UqMR_g/edit?tab=t.gg5ble8qlesq + new_version = f"{version_prefix}{version}" logger.info(f"New helm chart version will be: {new_version}") try: @@ -79,7 +80,7 @@ def get_oci_registry(chart_info: HelmChartInfo) -> str: raise ValueError("Error: registry doesn't seem to be set in HelmChartInfo.") if not repo: - raise ValueError("Error: reposiotry doesn't seem to be set in HelmChartInfo.") + raise ValueError("Error: repository doesn't seem to be set in HelmChartInfo.") oci_registry = f"oci://{registry}/{repo}" logger.info(f"Determined OCI Registry: {oci_registry}") @@ -89,7 +90,7 @@ def get_oci_registry(chart_info: HelmChartInfo) -> str: def publish_helm_chart(chart_info: HelmChartInfo, build_scenario): try: oci_registry = get_oci_registry(chart_info) - chart_name, chart_version = update_chart_and_get_metadata(CHART_DIR, build_scenario) + chart_name, chart_version = update_chart_and_get_metadata(CHART_DIR, chart_info.version_prefix) tgz_filename = f"{chart_name}-{chart_version}.tgz" logger.info(f"Packaging chart: {chart_name} with Version: {chart_version}") @@ -121,6 +122,5 @@ def main(): if __name__ == "__main__": try: main() - except Exception as e: - logger.error(f"Failure in the helm publishing process {e}") - sys.exit(1) + except Exception as main_err: + raise Exception(f"Failure in the helm publishing process {main_err}") diff --git a/scripts/release/tests/build_info_test.py b/scripts/release/tests/build_info_test.py index e6d44e9df..411f569c2 100644 --- a/scripts/release/tests/build_info_test.py +++ b/scripts/release/tests/build_info_test.py @@ -91,6 +91,7 @@ def test_load_build_info_development(): }, helm_charts={ "mongodb-kubernetes": HelmChartInfo( + version_prefix="0.0.0+", registry="268558157000.dkr.ecr.us-east-1.amazonaws.com", repository="dev/mongodb/helm-charts", region="us-east-1", @@ -185,6 +186,7 @@ def test_load_build_info_patch(): }, helm_charts={ "mongodb-kubernetes": HelmChartInfo( + version_prefix="0.0.0+", region="us-east-1", repository="dev/mongodb/helm-charts", registry="268558157000.dkr.ecr.us-east-1.amazonaws.com", @@ -308,10 +310,11 @@ def test_load_build_info_staging(): }, helm_charts={ "mongodb-kubernetes": HelmChartInfo( + sign=True, + version_prefix="0.0.0+", registry="268558157000.dkr.ecr.us-east-1.amazonaws.com", repository="staging/mongodb/helm-charts", region="us-east-1", - sign=True, ) }, ) @@ -419,10 +422,9 @@ def test_load_build_info_release(): }, helm_charts={ "mongodb-kubernetes": HelmChartInfo( + sign=True, registry="quay.io", repository="mongodb/helm-charts", - region=None, - sign=True, ) }, ) From e1700ca71d113a48418733a5cb648d8d0c673880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kara=C5=9B?= Date: Tue, 28 Oct 2025 16:26:15 +0100 Subject: [PATCH 23/26] Fixes --- .../templates/mongodb-enterprise-tests.yaml | 8 +-- scripts/release/publish_helm_chart.py | 66 ++++++++++++------- scripts/release/publish_helm_chart.sh | 4 +- 3 files changed, 48 insertions(+), 30 deletions(-) diff --git a/scripts/evergreen/deployments/test-app/templates/mongodb-enterprise-tests.yaml b/scripts/evergreen/deployments/test-app/templates/mongodb-enterprise-tests.yaml index 7abfd58ab..198374789 100644 --- a/scripts/evergreen/deployments/test-app/templates/mongodb-enterprise-tests.yaml +++ b/scripts/evergreen/deployments/test-app/templates/mongodb-enterprise-tests.yaml @@ -174,14 +174,14 @@ spec: - name: OM_DEBUG_HTTP value: "{{ .Values.omDebugHttp }}" {{ end }} + {{ if .Values.helm.oci.version }} + - name: OCI_HELM_VERSION + value: "{{ .Values.helm.oci.version }}" + {{ end }} {{ if .Values.helm.oci.registry }} - name: OCI_HELM_REGISTRY value: "{{ .Values.helm.oci.registry }}" {{ end }} - {{ if .Values.operator.version }} - - name: OPERATOR_VERSION - value: "{{ .Values.operator.version }}" - {{ end }} {{ if .Values.helm.oci.repository }} - name: OCI_HELM_REPOSITORY value: "{{ .Values.helm.oci.repository }}" diff --git a/scripts/release/publish_helm_chart.py b/scripts/release/publish_helm_chart.py index 2593e0eb9..6121f9506 100644 --- a/scripts/release/publish_helm_chart.py +++ b/scripts/release/publish_helm_chart.py @@ -3,6 +3,7 @@ import subprocess import yaml +from release.build.build_scenario import SUPPORTED_SCENARIOS from lib.base_logger import logger from scripts.release.build.build_info import * @@ -25,15 +26,11 @@ def run_command(command: list[str]): ) -# update_chart_and_get_metadata updates the helm chart's Chart.yaml and sets the version -# to either evg patch id or commit which is set in OPERATOR_VERSION. -def update_chart_and_get_metadata(chart_dir: str, version_prefix: str = None) -> tuple[str, str]: +# update_chart_and_get_metadata updates the helm chart's Chart.yaml and sets the proper version +# When we publish the helm chart to dev and staging we append `0.0.0+` in the chart version, details are +# here https://docs.google.com/document/d/1eJ8iKsI0libbpcJakGjxcPfbrTn8lmcZDbQH1UqMR_g/edit?tab=t.gg5ble8qlesq +def update_chart_and_get_metadata(chart_dir: str, version: str) -> tuple[str, str]: chart_path = os.path.join(chart_dir, "Chart.yaml") - version = os.environ.get("OPERATOR_VERSION") - if not version: - raise ValueError( - "Error: Environment variable 'OPERATOR_VERSION' must be set to determine the chart version to publish." - ) if not os.path.exists(chart_path): raise FileNotFoundError( @@ -51,23 +48,18 @@ def update_chart_and_get_metadata(chart_dir: str, version_prefix: str = None) -> except Exception as e: raise Exception(f"Unable to load Chart.yaml from dir {chart_path}: {e}") - # If version_prefix is not specified, the chart.yaml would already have correct chart version - if version_prefix is None: + if data["version"] == version: + logger.info(f"Chart '{chart_name}' already has version '{version}'. No update needed.") return chart_name, version - # When we publish the helm chart to dev and staging we append `0.0.0+` in the chart version, details are - # here https://docs.google.com/document/d/1eJ8iKsI0libbpcJakGjxcPfbrTn8lmcZDbQH1UqMR_g/edit?tab=t.gg5ble8qlesq - new_version = f"{version_prefix}{version}" - logger.info(f"New helm chart version will be: {new_version}") - try: - data["version"] = new_version + data["version"] = version with open(chart_path, "w") as f: yaml.safe_dump(data, f, sort_keys=False) - logger.info(f"Successfully updated version for chart '{chart_name}' to '{new_version}'.") - return chart_name, new_version + logger.info(f"Successfully updated version for chart '{chart_name}' to '{version}'.") + return chart_name, version except Exception as e: raise RuntimeError(f"Failed to read or update Chart.yaml: {e}") @@ -87,16 +79,22 @@ def get_oci_registry(chart_info: HelmChartInfo) -> str: return oci_registry -def publish_helm_chart(chart_info: HelmChartInfo, build_scenario): +def publish_helm_chart(chart_info: HelmChartInfo, operator_version: str): try: - oci_registry = get_oci_registry(chart_info) - chart_name, chart_version = update_chart_and_get_metadata(CHART_DIR, chart_info.version_prefix) + # If version_prefix is not specified, the chart.yaml would already have correct chart version + if chart_info.version_prefix is not None: + helm_version = f"{chart_info.version_prefix}{operator_version}" + else: + helm_version = operator_version + + chart_name, chart_version = update_chart_and_get_metadata(CHART_DIR, helm_version) tgz_filename = f"{chart_name}-{chart_version}.tgz" logger.info(f"Packaging chart: {chart_name} with Version: {chart_version}") package_command = ["helm", "package", CHART_DIR] run_command(package_command) + oci_registry = get_oci_registry(chart_info) logger.info(f"Pushing chart to registry: {oci_registry}") push_command = ["helm", "push", tgz_filename, oci_registry] run_command(push_command) @@ -108,15 +106,35 @@ def publish_helm_chart(chart_info: HelmChartInfo, build_scenario): def main(): parser = argparse.ArgumentParser( - description="Script to publish helm chart to the OCI container registry, based on the build scenario." + description="Script to publish helm chart to the OCI container registry, based on the build scenario.", + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + parser.add_argument( + "-b", + "--build-scenario", + metavar="", + action="store", + required=True, + type=str, + choices=SUPPORTED_SCENARIOS, + help=f"""Build scenario when reading configuration from 'build_info.json'. +Options: {", ".join(SUPPORTED_SCENARIOS)}. For '{BuildScenario.DEVELOPMENT}' the '{BuildScenario.PATCH}' scenario is used to read values from 'build_info.json'""", + ) + parser.add_argument( + "-v", + "--version", + metavar="", + action="store", + required=True, + type=str, + help="Operator version to use when publishing helm chart", ) - parser.add_argument("--build_scenario", type=str, help="Build scenario (e.g., patch, staging etc).") args = parser.parse_args() build_scenario = args.build_scenario build_info = load_build_info(build_scenario) - return publish_helm_chart(build_info.helm_charts["mongodb-kubernetes"], build_scenario) + return publish_helm_chart(build_info.helm_charts["mongodb-kubernetes"], args.version) if __name__ == "__main__": diff --git a/scripts/release/publish_helm_chart.sh b/scripts/release/publish_helm_chart.sh index 5321bffd2..34df4ab49 100755 --- a/scripts/release/publish_helm_chart.sh +++ b/scripts/release/publish_helm_chart.sh @@ -2,10 +2,10 @@ # Instead of calling the publish_helm_chart.py directly from .evergreen-functions.yaml # we are calling that via this .sh so that we can easily pass build_scenario from env var that -# is set via context files. Using the env vars, set via context files, in .evergreen configuraiton +# is set via context files. Using the env vars, set via context files, in .evergreen configuration # is not that straightforward. set -Eeou pipefail source scripts/dev/set_env_context.sh -scripts/dev/run_python.sh scripts/release/publish_helm_chart.py --build_scenario "${BUILD_SCENARIO}" +scripts/dev/run_python.sh scripts/release/publish_helm_chart.py --build_scenario "${BUILD_SCENARIO}" --version "${OPERATOR_VERSION}" From 2cc7bbd7ba29fa81ec04c4573481fc82ec39fa93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kara=C5=9B?= Date: Thu, 30 Oct 2025 12:14:14 +0100 Subject: [PATCH 24/26] Fix prefix concatenation --- docker/mongodb-kubernetes-tests/kubetester/helm.py | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/docker/mongodb-kubernetes-tests/kubetester/helm.py b/docker/mongodb-kubernetes-tests/kubetester/helm.py index e2ca8bda3..cd29bf395 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/helm.py +++ b/docker/mongodb-kubernetes-tests/kubetester/helm.py @@ -314,18 +314,9 @@ def helm_chart_path_and_version(helm_chart_path: str, operator_version: str) -> if local_operator(): return LOCAL_HELM_CHART_DIR, "" - # if operator_version is not specified, and we are not installing the MCK or MEKO chart - # it would mean we want to install OCI published helm chart. - if not operator_version and helm_chart_path not in ( - MCK_HELM_CHART, - LEGACY_OPERATOR_CHART, - ): - non_semver_operator_version = os.environ.get(OCI_HELM_VERSION) - operator_version = f"0.0.0+{non_semver_operator_version}" - - # helm_chart_path not being passed would mean we are on evg env and would like to - # install helm chart from OCI registry. + # helm_chart_path not being passed would mean we would like to install helm chart from OCI registry. if not helm_chart_path: + operator_version = os.environ.get(OCI_HELM_VERSION) registry, repository, region = oci_chart_info() # If ECR we need to login first to the OCI container registry if registry == OCI_HELM_REGISTRY_ECR: From c482251db36122f5cfe2d18b5295824f1d651717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kara=C5=9B?= Date: Thu, 30 Oct 2025 13:24:43 +0100 Subject: [PATCH 25/26] Fix publish_helm_chart task --- .evergreen.yml | 22 ++++++++++++++++++++++ scripts/release/publish_helm_chart.sh | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.evergreen.yml b/.evergreen.yml index d75a96c26..5b4a24eda 100644 --- a/.evergreen.yml +++ b/.evergreen.yml @@ -71,6 +71,8 @@ variables: variant: init_test_run - name: build_mco_test_image variant: init_test_run + - name: publish_helm_chart + variant: init_test_run - &setup_group setup_group_can_fail_task: true @@ -142,6 +144,8 @@ variables: variant: init_test_run - name: build_init_om_images_ubi variant: init_test_run + - name: publish_helm_chart + variant: init_test_run - &base_om7_dependency_with_race depends_on: @@ -159,6 +163,8 @@ variables: variant: init_test_run - name: build_init_om_images_ubi variant: init_test_run + - name: publish_helm_chart + variant: init_test_run # Any change to base_om8_dependency should be reflected to its copy in .evergreen-snippets.yml - &base_om8_dependency @@ -177,6 +183,8 @@ variables: variant: init_test_run - name: build_init_om_images_ubi variant: init_test_run + - name: publish_helm_chart + variant: init_test_run parameters: - key: evergreen_retry @@ -1287,6 +1295,8 @@ buildvariants: variant: init_test_run - name: build_init_database_image_ubi variant: init_test_run + - name: publish_helm_chart + variant: init_test_run tasks: - name: e2e_custom_domain_task_group @@ -1425,6 +1435,8 @@ buildvariants: variant: init_test_run - name: build_database_image_ubi variant: init_test_run + - name: publish_helm_chart + variant: init_test_run - name: build_test_image_ibm variant: init_test_run_ibm_power tasks: @@ -1447,6 +1459,8 @@ buildvariants: variant: init_test_run - name: build_database_image_ubi variant: init_test_run + - name: publish_helm_chart + variant: init_test_run - name: build_test_image_ibm variant: init_test_run_ibm_power tasks: @@ -1469,6 +1483,8 @@ buildvariants: variant: init_test_run - name: build_database_image_ubi variant: init_test_run + - name: publish_helm_chart + variant: init_test_run - name: build_test_image_ibm variant: init_test_run_ibm_z tasks: @@ -1489,6 +1505,8 @@ buildvariants: variant: init_test_run - name: build_init_database_image_ubi variant: init_test_run + - name: publish_helm_chart + variant: init_test_run - name: build_test_image_ibm variant: init_test_run_ibm_z tasks: @@ -1507,6 +1525,8 @@ buildvariants: variant: init_test_run - name: build_database_image_ubi variant: init_test_run + - name: publish_helm_chart + variant: init_test_run - name: build_test_image_arm variant: init_test_run_arm tasks: @@ -1523,6 +1543,8 @@ buildvariants: variant: init_test_run - name: build_init_database_image_ubi variant: init_test_run + - name: publish_helm_chart + variant: init_test_run - name: build_test_image_arm variant: init_test_run_arm tasks: diff --git a/scripts/release/publish_helm_chart.sh b/scripts/release/publish_helm_chart.sh index 34df4ab49..29f35d5f6 100755 --- a/scripts/release/publish_helm_chart.sh +++ b/scripts/release/publish_helm_chart.sh @@ -8,4 +8,4 @@ set -Eeou pipefail source scripts/dev/set_env_context.sh -scripts/dev/run_python.sh scripts/release/publish_helm_chart.py --build_scenario "${BUILD_SCENARIO}" --version "${OPERATOR_VERSION}" +scripts/dev/run_python.sh scripts/release/publish_helm_chart.py --build-scenario "${BUILD_SCENARIO}" --version "${OPERATOR_VERSION}" From 1ee164ad0c8b7d084f17b0ff4eafac77adaea061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kara=C5=9B?= Date: Fri, 31 Oct 2025 10:36:43 +0100 Subject: [PATCH 26/26] Fix multicluster tests --- .../kubetester/helm.py | 8 ++- .../tests/conftest.py | 3 + scripts/release/publish_helm_chart.py | 55 +++---------------- 3 files changed, 15 insertions(+), 51 deletions(-) diff --git a/docker/mongodb-kubernetes-tests/kubetester/helm.py b/docker/mongodb-kubernetes-tests/kubetester/helm.py index cd29bf395..66523f012 100644 --- a/docker/mongodb-kubernetes-tests/kubetester/helm.py +++ b/docker/mongodb-kubernetes-tests/kubetester/helm.py @@ -1,5 +1,4 @@ import glob -import logging import os import re import subprocess @@ -30,7 +29,7 @@ def helm_template( command_args.append("--show-only") command_args.append(templates) - args = ("helm", "template", *(command_args), _helm_chart_dir(helm_chart_path)) + args = ("helm", "template", *command_args, _helm_chart_dir(helm_chart_path)) logger.info(" ".join(args)) yaml_file_name = "{}.yaml".format(str(uuid.uuid4())) @@ -316,7 +315,10 @@ def helm_chart_path_and_version(helm_chart_path: str, operator_version: str) -> # helm_chart_path not being passed would mean we would like to install helm chart from OCI registry. if not helm_chart_path: - operator_version = os.environ.get(OCI_HELM_VERSION) + # If operator_version is not passed, we want to install the current version. + if not operator_version: + operator_version = os.environ.get(OCI_HELM_VERSION) + registry, repository, region = oci_chart_info() # If ECR we need to login first to the OCI container registry if registry == OCI_HELM_REGISTRY_ECR: diff --git a/docker/mongodb-kubernetes-tests/tests/conftest.py b/docker/mongodb-kubernetes-tests/tests/conftest.py index 2269e5925..818fce848 100644 --- a/docker/mongodb-kubernetes-tests/tests/conftest.py +++ b/docker/mongodb-kubernetes-tests/tests/conftest.py @@ -22,6 +22,7 @@ from kubetester.awss3client import AwsS3Client from kubetester.consts import * from kubetester.helm import ( + helm_chart_path_and_version, helm_install_from_chart, helm_repo_add, ) @@ -837,6 +838,8 @@ def _install_multi_cluster_operator( # The Operator will be installed from the following repo, so adding it first helm_repo_add("mongodb", "https://mongodb.github.io/helm-charts") + helm_chart_path, operator_version = helm_chart_path_and_version(helm_chart_path, custom_operator_version) + prepare_multi_cluster_namespaces( namespace, multi_cluster_operator_installation_config, diff --git a/scripts/release/publish_helm_chart.py b/scripts/release/publish_helm_chart.py index 3ff6111ef..87fc27e08 100644 --- a/scripts/release/publish_helm_chart.py +++ b/scripts/release/publish_helm_chart.py @@ -1,14 +1,12 @@ import argparse -import os import subprocess -import yaml - from lib.base_logger import logger from scripts.release.build.build_info import * from scripts.release.build.build_scenario import SUPPORTED_SCENARIOS CHART_DIR = "helm_chart" +MONGODB_KUBERNETES_CHART = "mongodb-kubernetes" def run_command(command: list[str]): @@ -26,44 +24,6 @@ def run_command(command: list[str]): ) -# update_chart_and_get_metadata updates the helm chart's Chart.yaml and sets the proper version -# When we publish the helm chart to dev and staging we append `0.0.0+` in the chart version, details are -# here https://docs.google.com/document/d/1eJ8iKsI0libbpcJakGjxcPfbrTn8lmcZDbQH1UqMR_g/edit?tab=t.gg5ble8qlesq -def update_chart_and_get_metadata(chart_dir: str, version: str) -> tuple[str, str]: - chart_path = os.path.join(chart_dir, "Chart.yaml") - - if not os.path.exists(chart_path): - raise FileNotFoundError( - f"Error: Chart.yaml not found in directory '{chart_dir}'. " - "Please ensure the directory exists and contains a valid Chart.yaml." - ) - - try: - with open(chart_path, "r") as f: - data = yaml.safe_load(f) - - chart_name = data.get("name") - if not chart_name: - raise ValueError("Chart.yaml is missing required 'name' field.") - except Exception as e: - raise Exception(f"Unable to load Chart.yaml from dir {chart_path}: {e}") - - if data["version"] == version: - logger.info(f"Chart '{chart_name}' already has version '{version}'. No update needed.") - return chart_name, version - - try: - data["version"] = version - - with open(chart_path, "w") as f: - yaml.safe_dump(data, f, sort_keys=False) - - logger.info(f"Successfully updated version for chart '{chart_name}' to '{version}'.") - return chart_name, version - except Exception as e: - raise RuntimeError(f"Failed to read or update Chart.yaml: {e}") - - def get_oci_registry(chart_info: HelmChartInfo) -> str: registry = chart_info.registry repo = chart_info.repository @@ -79,19 +39,18 @@ def get_oci_registry(chart_info: HelmChartInfo) -> str: return oci_registry -def publish_helm_chart(chart_info: HelmChartInfo, operator_version: str): +def publish_helm_chart(chart_name: str, chart_info: HelmChartInfo, operator_version: str): try: - # If version_prefix is not specified, the chart.yaml would already have correct chart version + # If version_prefix is not specified, use the operator_version as is. if chart_info.version_prefix is not None: - helm_version = f"{chart_info.version_prefix}{operator_version}" + chart_version = f"{chart_info.version_prefix}{operator_version}" else: - helm_version = operator_version + chart_version = operator_version - chart_name, chart_version = update_chart_and_get_metadata(CHART_DIR, helm_version) tgz_filename = f"{chart_name}-{chart_version}.tgz" logger.info(f"Packaging chart: {chart_name} with Version: {chart_version}") - package_command = ["helm", "package", CHART_DIR] + package_command = ["helm", "package", "--version", chart_version, CHART_DIR] run_command(package_command) oci_registry = get_oci_registry(chart_info) @@ -134,7 +93,7 @@ def main(): build_scenario = args.build_scenario build_info = load_build_info(build_scenario) - return publish_helm_chart(build_info.helm_charts["mongodb-kubernetes"], args.version) + return publish_helm_chart(MONGODB_KUBERNETES_CHART, build_info.helm_charts[MONGODB_KUBERNETES_CHART], args.version) if __name__ == "__main__":