Skip to content

Commit 1455760

Browse files
authored
Merge branch 'main' into logging
2 parents f726b5e + 4b3540a commit 1455760

File tree

11 files changed

+73
-42
lines changed

11 files changed

+73
-42
lines changed

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ repos:
3636
exclude: .*/__snapshots__/.*|.*-input\.json$|^semgrep\.yaml$
3737

3838
- repo: https://github.com/astral-sh/ruff-pre-commit
39-
rev: v0.15.6
39+
rev: v0.15.7
4040
hooks:
4141
- id: ruff
4242
- id: ruff-format
4343

4444
- repo: https://github.com/gitleaks/gitleaks
45-
rev: v8.30.1
45+
rev: v8.30.0
4646
hooks:
4747
- id: gitleaks
4848

@@ -90,7 +90,7 @@ repos:
9090
- id: actionlint
9191

9292
- repo: https://github.com/DavidAnson/markdownlint-cli2
93-
rev: v0.21.0
93+
rev: v0.22.0
9494
hooks:
9595
- id: markdownlint-cli2
9696
args:

CONSTITUTION.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ All code MUST consider security implications.
7979
- Avoid running destructive commands without explicit user confirmation
8080
- Use detect-secrets and gitleaks pre-commit hooks to prevent secret leakage
8181
- Test code MUST NOT introduce vulnerabilities into the tested systems
82+
- Use `utilities.path_utils.resolve_repo_path` to resolve and validate any user-supplied or parameterized file paths, preventing path-traversal and symlink-escape outside the repository root
8283
- JIRA ticket links are allowed in PRs and commit messages (our Jira is public)
8384
- Do NOT reference internal-only resources (Jenkins, Confluence, Slack threads) in code, PRs, or commit messages
8485
- Do NOT link embargoed or security-restricted (RH-employee-only) tickets

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ output-format = "grouped"
66
extend-exclude = ["utilities/manifests"]
77

88
[tool.ruff.lint]
9-
external = ["E501"]
9+
external = ["E501", "FCN001"]
1010

1111
[tool.ruff.format]
1212
exclude = [".git", ".venv", ".mypy_cache", ".tox", "__pycache__", "utilities/manifests"]

tests/llama_stack/conftest.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import os
22
from collections.abc import Callable, Generator
3-
from pathlib import Path
43
from typing import Any
54

65
import httpx
@@ -810,7 +809,6 @@ def vector_store(
810809
try:
811810
vector_store_upload_doc_sources(
812811
doc_sources=doc_sources,
813-
repo_root=Path(request.config.rootdir).resolve(),
814812
llama_stack_client=unprivileged_llama_stack_client,
815813
vector_store=vector_store,
816814
vector_io_provider=vector_io_provider,

tests/llama_stack/utils.py

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
)
2121
from utilities.exceptions import UnexpectedResourceCountError
2222
from utilities.opendatahub_logger import get_logger
23+
from utilities.path_utils import resolve_repo_path
2324
from utilities.resources.llama_stack_distribution import LlamaStackDistribution
2425

2526
LOGGER = get_logger(name=__name__)
@@ -279,38 +280,32 @@ def vector_store_create_file_from_path(
279280

280281

281282
def vector_store_upload_doc_sources(
282-
doc_sources: Any,
283-
repo_root: Path,
283+
doc_sources: list[str],
284284
llama_stack_client: LlamaStackClient,
285285
vector_store: Any,
286286
vector_io_provider: str,
287287
) -> None:
288288
"""Upload parametrized document sources (URLs and repo-local paths) to a vector store.
289289
290-
Resolves each local path under ``repo_root`` and re-resolves directory entries to avoid
291-
symlink escape outside the repository.
290+
Resolves each local path via ``resolve_repo_path`` and re-resolves directory entries
291+
to avoid symlink escape outside the repository.
292292
293293
Args:
294294
doc_sources: List of URL or path strings (repo-relative or absolute under repo root).
295-
repo_root: Resolved repository root; local paths must resolve under this directory.
296295
llama_stack_client: Client used for file and vector store APIs.
297296
vector_store: Target vector store (must expose ``id``).
298297
vector_io_provider: Provider id for log context only.
299298
300299
Raises:
301-
TypeError: If ``doc_sources`` is not a list.
302-
ValueError: If a local path resolves outside ``repo_root``.
300+
ValueError: If a local path resolves outside the repo root.
303301
FileNotFoundError: If a file or non-empty directory source is missing.
304302
"""
305-
if not isinstance(doc_sources, list):
306-
raise TypeError(f"doc_sources must be a list[str], got {type(doc_sources).__name__}")
307303
LOGGER.info(
308304
"Uploading doc_sources to vector_store (provider_id=%s, id=%s): %s",
309305
vector_io_provider,
310306
vector_store.id,
311307
doc_sources,
312308
)
313-
repo_root_resolved = repo_root.resolve()
314309
for source in doc_sources:
315310
if source.startswith(("http://", "https://")):
316311
vector_store_create_file_from_url(
@@ -319,25 +314,14 @@ def vector_store_upload_doc_sources(
319314
vector_store=vector_store,
320315
)
321316
continue
322-
raw_path = Path(source) # noqa: FCN001
323-
resolved_source = raw_path.resolve() if raw_path.is_absolute() else (repo_root_resolved / raw_path).resolve()
324-
if not resolved_source.is_relative_to(repo_root_resolved):
325-
raise ValueError(
326-
f"doc_sources path must be under repo root ({repo_root_resolved}): {source!r}",
327-
)
328-
source_path = resolved_source
317+
source_path = resolve_repo_path(source=source)
329318

330319
if source_path.is_dir():
331320
files = sorted(source_path.iterdir())
332321
if not files:
333322
raise FileNotFoundError(f"No files found in directory: {source_path}")
334323
for file_path in files:
335-
file_path_resolved = file_path.resolve(strict=True)
336-
if not file_path_resolved.is_relative_to(repo_root_resolved):
337-
raise ValueError(
338-
f"doc_sources directory entry must resolve under repo root "
339-
f"({repo_root_resolved}): {file_path!r} -> {file_path_resolved!r}",
340-
)
324+
file_path_resolved = resolve_repo_path(source=file_path)
341325
if not file_path_resolved.is_file():
342326
continue
343327
vector_store_create_file_from_path(

tests/model_serving/model_server/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def verify_inference_response(
8888

8989
elif (
9090
isinstance(inference_service, InferenceGraph)
91-
and inference.deployment_mode == KServeDeploymentType.RAW_DEPLOYMENT
91+
and inference.deployment_mode in KServeDeploymentType.RAW_DEPLOYMENT_MODES
9292
):
9393
assert "x-forbidden-reason: Access to the InferenceGraph is not allowed" in res["output"]
9494

utilities/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
class KServeDeploymentType:
88
SERVERLESS: str = "Serverless"
99
RAW_DEPLOYMENT: str = "RawDeployment"
10+
STANDARD: str = "Standard"
1011
MODEL_MESH: str = "ModelMesh"
1112

13+
RAW_DEPLOYMENT_MODES: tuple[str, ...] = (RAW_DEPLOYMENT, STANDARD)
14+
1215

1316
class ModelFormat:
1417
CAIKIT: str = "caikit"

utilities/general.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,9 @@ def create_isvc_label_selector_str(isvc: InferenceService, resource_type: str, r
173173
174174
"""
175175
deployment_mode = isvc.instance.metadata.annotations.get(Annotations.KserveIo.DEPLOYMENT_MODE)
176-
if deployment_mode in (
177-
KServeDeploymentType.SERVERLESS,
178-
KServeDeploymentType.RAW_DEPLOYMENT,
176+
if (
177+
deployment_mode == KServeDeploymentType.SERVERLESS
178+
or deployment_mode in KServeDeploymentType.RAW_DEPLOYMENT_MODES
179179
):
180180
return f"{isvc.ApiGroup.SERVING_KSERVE_IO}/inferenceservice={isvc.name}"
181181

utilities/inference_utils.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def is_service_exposed(self) -> bool:
118118
"""
119119
labels = self.inference_service.labels
120120

121-
if self.deployment_mode == KServeDeploymentType.RAW_DEPLOYMENT:
121+
if self.deployment_mode in KServeDeploymentType.RAW_DEPLOYMENT_MODES:
122122
if isinstance(self.inference_service, InferenceGraph):
123123
# For InferenceGraph, the logic is similar as in Serverless. Only the label is different.
124124
return not (labels and labels.get(Labels.Kserve.NETWORKING_KSERVE_IO) == "cluster-local")
@@ -310,7 +310,7 @@ def generate_command(
310310

311311
elif self.protocol == "grpc":
312312
cmd_exec = "grpcurl -connect-timeout 10 "
313-
if self.deployment_mode == KServeDeploymentType.RAW_DEPLOYMENT:
313+
if self.deployment_mode in KServeDeploymentType.RAW_DEPLOYMENT_MODES:
314314
cmd_exec += " --plaintext "
315315

316316
else:
@@ -536,10 +536,9 @@ def get_target_port(self, svc: Service) -> int:
536536
and port.protocol.lower() == svc_protocol.lower()
537537
and port.name == self.protocol
538538
) or (
539-
self.deployment_mode
540-
in (
541-
KServeDeploymentType.RAW_DEPLOYMENT,
542-
KServeDeploymentType.SERVERLESS,
539+
(
540+
self.deployment_mode in KServeDeploymentType.RAW_DEPLOYMENT_MODES
541+
or self.deployment_mode == KServeDeploymentType.SERVERLESS
543542
)
544543
and port.protocol.lower() == svc_protocol.lower()
545544
):
@@ -679,15 +678,18 @@ def create_isvc(
679678
_annotations = {Annotations.KserveIo.DEPLOYMENT_MODE: deployment_mode}
680679

681680
# model mesh auth is set in ServingRuntime
682-
if enable_auth and deployment_mode in {KServeDeploymentType.SERVERLESS, KServeDeploymentType.RAW_DEPLOYMENT}:
681+
if enable_auth and (
682+
deployment_mode == KServeDeploymentType.SERVERLESS
683+
or deployment_mode in KServeDeploymentType.RAW_DEPLOYMENT_MODES
684+
):
683685
_annotations[Annotations.KserveAuth.SECURITY] = "true"
684686

685687
# default to True if deployment_mode is Serverless (default behavior of Serverless) if was not provided by the user
686688
# model mesh external route is set in ServingRuntime
687689
if external_route is None and deployment_mode == KServeDeploymentType.SERVERLESS:
688690
external_route = True
689691

690-
if external_route and deployment_mode == KServeDeploymentType.RAW_DEPLOYMENT:
692+
if external_route and deployment_mode in KServeDeploymentType.RAW_DEPLOYMENT_MODES:
691693
labels[Labels.Kserve.NETWORKING_KSERVE_IO] = Labels.Kserve.EXPOSED
692694

693695
if deployment_mode == KServeDeploymentType.SERVERLESS and external_route is False:

utilities/infra.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ def wait_for_inference_deployment_replicas(
272272
# to be set in deployment spec by HPA
273273
if (
274274
isvc.instance.metadata.annotations.get("serving.kserve.io/deploymentMode")
275-
== KServeDeploymentType.RAW_DEPLOYMENT
275+
in KServeDeploymentType.RAW_DEPLOYMENT_MODES
276276
):
277277
wait_for_replicas_in_deployment(
278278
deployment=deployment,

0 commit comments

Comments
 (0)