mirror of
https://github.com/hanzo-ml/kserve.git
synced 2026-10-30 20:53:49 +00:00
190 lines
6.8 KiB
Python
190 lines
6.8 KiB
Python
#!/usr/bin/env python3
|
|
|
|
# Copyright 2025 The KServe Authors.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""Component discovery and processing utilities."""
|
|
|
|
from pathlib import Path
|
|
from typing import Any, Optional
|
|
|
|
from . import bash_parser
|
|
from . import file_reader
|
|
from . import template_embedder
|
|
|
|
|
|
# Section markers for extraction
|
|
VARIABLES_SECTION_START = "# VARIABLES"
|
|
VARIABLES_SECTION_END = "# VARIABLES END"
|
|
INCLUDE_SECTION_START = "# INCLUDE_IN_GENERATED_SCRIPT_START"
|
|
INCLUDE_SECTION_END = "# INCLUDE_IN_GENERATED_SCRIPT_END"
|
|
|
|
|
|
def find_component_script(
|
|
component: str, infra_dir: Path, method: Optional[str] = None
|
|
) -> Optional[Path]:
|
|
"""Find component script following naming conventions with progressive folder search.
|
|
|
|
For a component like "gateway-api-crd" with method "helm", searches in order:
|
|
1. gateway-api-crd/manage.gateway-api-crd-helm.sh (method-specific in deepest folder)
|
|
2. gateway-api-crd/manage.gateway-api-crd.sh (base in deepest folder)
|
|
3. gateway-api/manage.gateway-api-crd-helm.sh (method-specific in parent folder)
|
|
4. gateway-api/manage.gateway-api-crd.sh (base in parent folder)
|
|
5. gateway/manage.gateway-api-crd-helm.sh (method-specific in grandparent folder)
|
|
6. gateway/manage.gateway-api-crd.sh (base in grandparent folder)
|
|
7. manage.gateway-api-crd-helm.sh (method-specific in root)
|
|
8. manage.gateway-api-crd.sh (base in root)
|
|
|
|
Args:
|
|
component: Component name (e.g., "gateway-api-crd")
|
|
infra_dir: Infrastructure directory path
|
|
method: Installation method (e.g., "helm", "kustomize"), optional
|
|
|
|
Returns:
|
|
Path to component script or None if not found
|
|
"""
|
|
# Generate folder candidates: gateway-api-crd → gateway-api → gateway → "" (root)
|
|
folder_candidates = []
|
|
parts = component.split("-")
|
|
for i in range(len(parts), 0, -1):
|
|
folder_candidates.append("-".join(parts[:i]))
|
|
folder_candidates.append("") # root directory
|
|
|
|
# For each folder, try to find the script (method-specific first, then base)
|
|
for folder in folder_candidates:
|
|
base_dir = infra_dir / folder if folder else infra_dir
|
|
|
|
# Try method-specific script first (higher priority)
|
|
if method:
|
|
path = base_dir / f"manage.{component}-{method}.sh"
|
|
if path.exists():
|
|
return path
|
|
|
|
# Try base script as fallback
|
|
path = base_dir / f"manage.{component}.sh"
|
|
if path.exists():
|
|
return path
|
|
|
|
return None
|
|
|
|
|
|
def process_component(
|
|
comp_config: dict[str, Any],
|
|
infra_dir: Path,
|
|
method: Optional[str] = None,
|
|
embed_templates: bool = False,
|
|
) -> dict[str, Any]:
|
|
"""Process single component: find script, extract and rename functions.
|
|
|
|
Args:
|
|
comp_config: Component configuration dict with keys:
|
|
- name: Component name
|
|
- env: Environment variables for this component
|
|
infra_dir: Infrastructure directory path
|
|
method: Installation method (e.g., "helm", "kustomize"), optional
|
|
embed_templates: Whether to discover and embed template files
|
|
|
|
Returns:
|
|
Processed component data dict with keys:
|
|
- name: Component name
|
|
- install_func: Renamed install function name
|
|
- uninstall_func: Renamed uninstall function name
|
|
- install_code: Install function code
|
|
- uninstall_code: Uninstall function code
|
|
- variables: List of variable declarations
|
|
- include_section: Code to include in generated script
|
|
- template_functions: Bash functions for embedded templates (if embed_templates=True)
|
|
- has_templates: Boolean indicating if templates were found
|
|
- env: Environment variables
|
|
|
|
Raises:
|
|
RuntimeError: If script or required functions not found
|
|
"""
|
|
name = comp_config["name"]
|
|
|
|
script_file = find_component_script(name, infra_dir, method)
|
|
if not script_file:
|
|
raise RuntimeError(f"Script not found for: {name} (method: {method})")
|
|
|
|
# Extract functions
|
|
install_raw = bash_parser.extract_bash_function(script_file, "install")
|
|
uninstall_raw = bash_parser.extract_bash_function(script_file, "uninstall")
|
|
|
|
if not install_raw:
|
|
raise RuntimeError(f"Function 'install()' not found in: {script_file}")
|
|
if not uninstall_raw:
|
|
raise RuntimeError(f"Function 'uninstall()' not found in: {script_file}")
|
|
|
|
# Extract variables and include section
|
|
variables = file_reader.extract_marked_section(
|
|
script_file,
|
|
VARIABLES_SECTION_START,
|
|
VARIABLES_SECTION_END,
|
|
preserve_indent=False,
|
|
skip_empty=True,
|
|
)
|
|
|
|
include_section = file_reader.extract_marked_section(
|
|
script_file,
|
|
INCLUDE_SECTION_START,
|
|
INCLUDE_SECTION_END,
|
|
preserve_indent=True,
|
|
skip_empty=False,
|
|
)
|
|
|
|
# Rename functions
|
|
suffix = name.replace("-", "_")
|
|
install_func = f"install_{suffix}"
|
|
uninstall_func = f"uninstall_{suffix}"
|
|
|
|
# Rename install function and its calls
|
|
install_code = bash_parser.rename_bash_function(
|
|
install_raw, "install", install_func
|
|
)
|
|
# Also rename any calls to uninstall within install function
|
|
install_code = bash_parser.rename_bash_function(
|
|
install_code, "uninstall", uninstall_func
|
|
)
|
|
|
|
# Rename uninstall function and its calls
|
|
uninstall_code = bash_parser.rename_bash_function(
|
|
uninstall_raw, "uninstall", uninstall_func
|
|
)
|
|
# Also rename any calls to install within uninstall function (less common but possible)
|
|
uninstall_code = bash_parser.rename_bash_function(
|
|
uninstall_code, "install", install_func
|
|
)
|
|
|
|
# Discover and embed template files if requested
|
|
template_functions = ""
|
|
if embed_templates:
|
|
templates = template_embedder.discover_component_templates(name, infra_dir)
|
|
if templates:
|
|
template_functions = template_embedder.generate_template_functions(
|
|
name, templates
|
|
)
|
|
|
|
return {
|
|
"name": name,
|
|
"install_func": install_func,
|
|
"uninstall_func": uninstall_func,
|
|
"install_code": install_code,
|
|
"uninstall_code": uninstall_code,
|
|
"variables": variables,
|
|
"include_section": include_section,
|
|
"template_functions": template_functions,
|
|
"has_templates": bool(template_functions),
|
|
"env": comp_config["env"],
|
|
}
|