Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

"""Image helper utilities for NeMo Platform jobs."""

from collections.abc import Callable

from nemo_platform_plugin.config import get_platform_config


def get_qualified_image(name: str, tag: str | None = None, registry: str | None = None) -> str:
"""Get a fully qualified Docker image name.

Builds an image reference in the format: {registry}/{name}:{tag}
"""
config = get_platform_config()

effective_registry = registry if registry is not None else config.image_registry
effective_tag = tag if tag is not None else config.image_tag

return f"{effective_registry}/{name}:{effective_tag}"


def image_builder(registry: str | None = None, tag: str | None = None) -> Callable[[str], str]:
"""Create a function that builds qualified image names with preset registry and tag."""
config = get_platform_config()

effective_registry = registry if registry is not None else config.image_registry
effective_tag = tag if tag is not None else config.image_tag

def _build(name: str) -> str:
return f"{effective_registry}/{name}:{effective_tag}"

return _build
33 changes: 33 additions & 0 deletions packages/nemo_platform_plugin/tests/test_jobs_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

from __future__ import annotations

from types import SimpleNamespace

import nemo_platform_plugin.jobs.image as image
Comment thread
SandyChapman marked this conversation as resolved.
Dismissed
import pytest
from nemo_platform_plugin.jobs.image import get_qualified_image, image_builder


@pytest.fixture
def platform_config(monkeypatch: pytest.MonkeyPatch) -> None:
config = SimpleNamespace(image_registry="registry.example.com/nemo", image_tag="test-tag")
monkeypatch.setattr(image, "get_platform_config", lambda: config)


def test_get_qualified_image_uses_platform_config(platform_config: None) -> None:
assert get_qualified_image("nmp-cpu-tasks") == "registry.example.com/nemo/nmp-cpu-tasks:test-tag"


def test_get_qualified_image_accepts_overrides(platform_config: None) -> None:
assert (
get_qualified_image("nmp-cpu-tasks", registry="nvcr.io/example", tag="25.10")
== "nvcr.io/example/nmp-cpu-tasks:25.10"
)


def test_image_builder_uses_platform_config_once(platform_config: None) -> None:
build_image = image_builder()

assert build_image("nmp-api") == "registry.example.com/nemo/nmp-api:test-tag"
75 changes: 0 additions & 75 deletions packages/nmp_common/src/nmp/common/jobs/image.py

This file was deleted.

2 changes: 1 addition & 1 deletion packages/nmp_testing/src/nmp/testing/e2e/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from typing import TYPE_CHECKING

from nemo_platform import NeMoPlatform
from nmp.common.jobs.image import image_builder
from nemo_platform_plugin.jobs.image import image_builder

if TYPE_CHECKING:
from .config import E2EConfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
)
from nemo_platform_plugin.jobs.constants import DEFAULT_JOB_STORAGE_PATH, PERSISTENT_JOB_STORAGE_PATH_ENVVAR
from nemo_platform_plugin.jobs.exceptions import PlatformJobCompilationError
from nmp.common.jobs.image import get_qualified_image
from nemo_platform_plugin.jobs.image import get_qualified_image
from pydantic import BaseModel


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
PlatformJobSpec,
PlatformJobStep,
)
from nmp.common.jobs.image import get_qualified_image
from nemo_platform_plugin.jobs.image import get_qualified_image
from pydantic import BaseModel


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
DEFAULT_JOB_STORAGE_PATH,
PERSISTENT_JOB_STORAGE_PATH_ENVVAR,
)
from nmp.common.jobs.image import get_qualified_image
from nemo_platform_plugin.jobs.image import get_qualified_image

EVALUATE_STEP_NAME = "evaluate"
_RESERVED_SECRET_ENV_NAMES = frozenset({PERSISTENT_JOB_STORAGE_PATH_ENVVAR})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
SubprocessExecutionProviderSpec,
job_route_factory,
)
from nemo_platform_plugin.jobs.image import get_qualified_image
from nemo_safe_synthesizer.config.external_results import SafeSynthesizerSummary
from nemo_safe_synthesizer_plugin.config import config
from nemo_safe_synthesizer_plugin.job_config import (
Expand All @@ -38,7 +39,6 @@
)
from nemo_safe_synthesizer_plugin.runtime import runtime_task_command
from nmp.common.jobs.exceptions import PlatformJobCompilationError
from nmp.common.jobs.image import get_qualified_image

logger = logging.getLogger(__name__)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ def controller_with_docker_and_igw(
Yields:
Tuple of (controller, model_cache, sdk, mock_nim_image, docker_test_context, async_sdk)
"""
from nmp.common.jobs.image import get_qualified_image as real_get_qualified_image
from nemo_platform_plugin.jobs.image import get_qualified_image as real_get_qualified_image

def patched_get_qualified_image(name: str, tag=None, registry=None):
if name in ["nmp-core", "nmp-api"]:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
ResourcesRequestsSpec,
ResourcesSpec,
)
from nemo_platform_plugin.jobs.image import get_qualified_image
from nmp.common.api.common import Page
from nmp.common.api.parsed_filter import ParsedFilter, make_filter_dep
from nmp.common.api.utils import generate_openapi_extra_params
from nmp.common.auth import AuthClient, get_auth_client
from nmp.common.entities.client import EntityNotFoundError, EntityValidationError
from nmp.common.jobs.image import get_qualified_image
from nmp.common.sdk_factory import get_async_platform_sdk
from nmp.common.service.dependencies import get_sdk_client
from nmp.core.models.api.dependencies import get_adapter_entity_service, get_model_entity_service
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@
from nemo_platform.types.inference.model_deployment import ModelDeployment
from nemo_platform.types.inference.model_deployment_config import ModelDeploymentConfig
from nemo_platform.types.models.model_entity import ModelEntity
from nemo_platform_plugin.jobs.image import get_qualified_image
from nmp.common.config import get_auth_config, get_platform_config
from nmp.common.config.base import LOOPBACK_ADDRESSES
from nmp.common.docker.gpu_pool import DockerGPUPool, GPUAllocationError
from nmp.common.jobs.image import get_qualified_image
from nmp.common.sdk_factory import get_sdk_on_behalf_of
from nmp.core.models.app import ModelWeightsType, get_model_weights_type, is_multi_llm_image, parse_model_name_revision
from nmp.core.models.app.constants import MODEL_MANAGED_BY_LABEL, MODEL_MANAGED_BY_MODELS_CONTROLLER
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ def controller_with_docker(
models_controller_container_cleanup,
):
"""Create controller with real Docker backend."""
from nmp.common.jobs.image import get_qualified_image as real_get_qualified_image
from nemo_platform_plugin.jobs.image import get_qualified_image as real_get_qualified_image

def patched_get_qualified_image(name: str, tag=None, registry=None):
if name in ["nmp-core", "nmp-api"]:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
ResourcesRequestsSpec,
ResourcesSpec,
)
from nemo_platform_plugin.jobs.image import get_qualified_image
from nmp.common.auth import AuthClient, auth_client_context
from nmp.common.entities.utils import parse_entity_ref
from nmp.common.jobs.constants import DEFAULT_JOB_STORAGE_PATH, PERSISTENT_JOB_STORAGE_PATH_ENVVAR
from nmp.common.jobs.exceptions import PlatformJobCompilationError
from nmp.common.jobs.image import get_qualified_image
from nmp.customizer.api.v2.jobs.schemas import (
CustomizationJobInput,
CustomizationJobOutput,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
ResourcesSpec,
StepLifecycle,
)
from nmp.common.jobs.image import get_qualified_image
from nemo_platform_plugin.jobs.image import get_qualified_image
from nmp.common.model_utils import is_embedding_model
from nmp.customizer.api.v2.jobs.schemas import (
AnyTraining,
Expand Down
2 changes: 1 addition & 1 deletion services/customizer/tests/test_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
from nemo_platform import AsyncNeMoPlatform, NotFoundError
from nemo_platform.types.models.model_entity import ModelEntity
from nemo_platform_plugin.jobs.api_factory import _validate_and_resolve_job_output
from nemo_platform_plugin.jobs.image import get_qualified_image
from nmp.common.auth import AuthClient, auth_client_context
from nmp.common.entities.client import EntityClient
from nmp.common.entities.constants import NAME_PATTERN
from nmp.common.entities.utils import get_random_id
from nmp.common.jobs.exceptions import PlatformJobCompilationError
from nmp.common.jobs.image import get_qualified_image
from nmp.customizer.api.v2.jobs.schemas import CustomizationJobInput, CustomizationJobOutput
from nmp.customizer.app.constants import (
DEFAULT_DATASET_PATH,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
PlatformJobSpec,
PlatformJobStep,
)
from nemo_platform_plugin.jobs.image import get_qualified_image
from nmp.common.jobs.constants import PERSISTENT_JOB_STORAGE_PATH_ENVVAR
from nmp.common.jobs.image import get_qualified_image
from nmp.evaluator.app.evalfactory.system import get_system_benchmark_handler
from nmp.evaluator.app.jobs.constants import NEMO_EVAL_FACTORY_JOB_CONFIG, resolve_eval_harness
from nmp.evaluator.app.jobs.fileset import get_fileset_step
Expand Down
2 changes: 1 addition & 1 deletion services/evaluator/src/nmp/evaluator/app/jobs/fileset.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
EnvironmentVariable,
PlatformJobStep,
)
from nemo_platform_plugin.jobs.image import get_qualified_image
from nmp.common.jobs.constants import (
DEFAULT_NEMO_JOB_STEP_CONFIG_FILE_PATH,
EPHEMERAL_TASK_STORAGE_PATH_ENVVAR,
PERSISTENT_JOB_STORAGE_PATH_ENVVAR,
)
from nmp.common.jobs.image import get_qualified_image
from nmp.evaluator.app.values import Dataset, Fileset, FilesetRef
from nmp.evaluator.config import settings

Expand Down
2 changes: 1 addition & 1 deletion services/evaluator/src/nmp/evaluator/app/jobs/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
PlatformJobSpec,
PlatformJobStep,
)
from nemo_platform_plugin.jobs.image import get_qualified_image
from nmp.common.jobs.constants import PERSISTENT_JOB_STORAGE_PATH_ENVVAR
from nmp.common.jobs.image import get_qualified_image
from nmp.evaluator.app.evalfactory.system import get_system_metric_handler
from nmp.evaluator.app.jobs.constants import (
EVALFACTORY_EVALUATION_JOB_FILE_NAME,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
from fastapi import FastAPI
from fastapi.testclient import TestClient
from nemo_platform_plugin.jobs.api_factory import _validate_and_resolve_job_output
from nemo_platform_plugin.jobs.image import get_qualified_image
from nmp.common.entities.client import EntityClient
from nmp.common.jobs.image import get_qualified_image
from nmp.evaluator.api.v2.benchmarks.endpoints import (
get_benchmarks_manager,
platform_job_config_compiler,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
from nemo_evaluator_sdk.values import AggregatedMetricResult
from nemo_evaluator_sdk.values.metrics import default_judge_prompt_template_chat
from nemo_platform_plugin.jobs.api_factory import _validate_and_resolve_job_output
from nemo_platform_plugin.jobs.image import get_qualified_image
from nmp.common.entities import EntityClient
from nmp.common.jobs.constants import EPHEMERAL_TASK_STORAGE_PATH_ENVVAR, PERSISTENT_JOB_STORAGE_PATH_ENVVAR
from nmp.common.jobs.image import get_qualified_image
from nmp.evaluator.api.v2.common.query_params import AggregateFieldNameList
from nmp.evaluator.api.v2.metrics.endpoints import (
create_metric,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
PlatformJobStep,
job_route_factory,
)
from nmp.common.jobs.image import get_qualified_image
from nemo_platform_plugin.jobs.image import get_qualified_image
from nmp.hello_world.api.v2.jobs.schemas import HelloWorldJobConfig


Expand Down
Loading