@@ -518,6 +518,12 @@ def submit_pipeline(
518518 "schedule. Use `Schedule(cron_expression=...)` instead."
519519 )
520520 cron_expression = deployment .schedule .cron_expression
521+
522+ # Prepare dependencies for pod creation
523+ registry_credentials , local_stores_path = self ._prepare_pod_dependencies (
524+ settings , stack
525+ )
526+
521527 cron_job_manifest , secret_manifests = build_cron_job_manifest (
522528 cron_expression = cron_expression ,
523529 run_name = orchestrator_run_name ,
@@ -535,18 +541,14 @@ def submit_pipeline(
535541 failed_jobs_history_limit = settings .failed_jobs_history_limit ,
536542 ttl_seconds_after_finished = settings .ttl_seconds_after_finished ,
537543 namespace = self .config .kubernetes_namespace ,
538- container_registry = stack .container_registry ,
539544 auto_generate_image_pull_secrets = settings .auto_generate_image_pull_secrets ,
540545 core_api = self ._k8s_core_api ,
546+ registry_credentials = registry_credentials ,
547+ local_stores_path = local_stores_path ,
541548 )
542549
543550 # Create imagePullSecrets first
544- create_image_pull_secrets_from_manifests (
545- secret_manifests = secret_manifests ,
546- core_api = self ._k8s_core_api ,
547- namespace = self .config .kubernetes_namespace ,
548- reuse_existing = False , # Orchestrator creates/updates all secrets
549- )
551+ self ._create_image_pull_secrets (secret_manifests )
550552
551553 self ._k8s_batch_api .create_namespaced_cron_job (
552554 body = cron_job_manifest ,
@@ -558,6 +560,11 @@ def submit_pipeline(
558560 )
559561 return None
560562 else :
563+ # Prepare dependencies for pod creation
564+ registry_credentials , local_stores_path = self ._prepare_pod_dependencies (
565+ settings , stack
566+ )
567+
561568 # Create and run the orchestrator pod.
562569 pod_manifest , secret_manifests = build_pod_manifest (
563570 run_name = orchestrator_run_name ,
@@ -572,18 +579,14 @@ def submit_pipeline(
572579 env = environment ,
573580 mount_local_stores = self .config .is_local ,
574581 namespace = self .config .kubernetes_namespace ,
575- container_registry = stack .container_registry ,
576582 auto_generate_image_pull_secrets = settings .auto_generate_image_pull_secrets ,
577583 core_api = self ._k8s_core_api ,
584+ registry_credentials = registry_credentials ,
585+ local_stores_path = local_stores_path ,
578586 )
579587
580588 # Create imagePullSecrets first
581- create_image_pull_secrets_from_manifests (
582- secret_manifests = secret_manifests ,
583- core_api = self ._k8s_core_api ,
584- namespace = self .config .kubernetes_namespace ,
585- reuse_existing = False , # Orchestrator creates/updates all secrets
586- )
589+ self ._create_image_pull_secrets (secret_manifests )
587590
588591 kube_utils .create_and_wait_for_pod_to_start (
589592 core_api = self ._k8s_core_api ,
@@ -650,6 +653,54 @@ def _get_service_account_name(
650653 )
651654 return service_account_name
652655
656+ def _prepare_pod_dependencies (
657+ self ,
658+ settings : KubernetesOrchestratorSettings ,
659+ stack : "Stack"
660+ ) -> Tuple [Optional [Tuple [str , str , str ]], Optional [str ]]:
661+ """Prepare dependencies needed for pod manifest creation.
662+
663+ Args:
664+ settings: The orchestrator settings.
665+ stack: The stack the pipeline will run on.
666+
667+ Returns:
668+ Tuple of (registry_credentials, local_stores_path).
669+ """
670+ # Get registry credentials if auto-generation is enabled
671+ registry_credentials = None
672+ if settings .auto_generate_image_pull_secrets :
673+ registry_credentials = self .get_kubernetes_image_pull_secret_data (
674+ stack .container_registry
675+ )
676+
677+ # Get local stores path if mounting local stores
678+ local_stores_path = None
679+ if self .config .is_local :
680+ from zenml .config .global_config import GlobalConfiguration
681+
682+ stack .check_local_paths ()
683+ local_stores_path = GlobalConfiguration ().local_stores_path
684+
685+ return registry_credentials , local_stores_path
686+
687+ def _create_image_pull_secrets (
688+ self ,
689+ secret_manifests : List [Dict [str , str ]],
690+ ) -> None :
691+ """Create imagePullSecrets in the cluster.
692+
693+ Args:
694+ secret_manifests: List of secret manifests for imagePullSecrets.
695+ """
696+ # Create imagePullSecrets first
697+ create_image_pull_secrets_from_manifests (
698+ secret_manifests = secret_manifests ,
699+ core_api = self ._k8s_core_api ,
700+ namespace = self .config .kubernetes_namespace ,
701+ reuse_existing = False , # Orchestrator creates/updates all secrets
702+ )
703+
653704 def get_orchestrator_run_id (self ) -> str :
654705 """Returns the active orchestrator run id.
655706
@@ -667,3 +718,59 @@ def get_orchestrator_run_id(self) -> str:
667718 "Unable to read run id from environment variable "
668719 f"{ ENV_ZENML_KUBERNETES_RUN_ID } ."
669720 )
721+
722+ def get_kubernetes_image_pull_secret_data (
723+ self , container_registry
724+ ) -> Optional [Tuple [str , str , str ]]:
725+ """Get container registry credentials for Kubernetes imagePullSecrets.
726+
727+ This method extracts credentials from the container registry for use
728+ in Kubernetes imagePullSecrets. It only works with this Kubernetes
729+ orchestrator since other orchestrators don't need imagePullSecrets.
730+
731+ Args:
732+ container_registry: The container registry to get credentials from.
733+
734+ Returns:
735+ Tuple of (registry_uri, username, password) if credentials are available,
736+ None otherwise. The registry_uri is normalized for use in Kubernetes
737+ imagePullSecrets.
738+ """
739+ from zenml .logger import get_logger
740+
741+ logger = get_logger (__name__ )
742+
743+ # Check if this is a local Kubernetes orchestrator
744+ if self .config .is_local :
745+ logger .debug (
746+ "Skipping ImagePullSecret generation for local Kubernetes orchestrator"
747+ )
748+ return None
749+
750+ logger .debug (
751+ f"Getting ImagePullSecret data for registry: { container_registry .config .uri } "
752+ )
753+
754+ credentials = container_registry .credentials
755+ if not credentials :
756+ logger .debug ("No credentials found for container registry" )
757+ return None
758+
759+ username , password = credentials
760+ registry_uri = container_registry .registry_server_uri
761+
762+ logger .debug (
763+ f"Found credentials - username: { username [:3 ]} ***, registry_uri: { registry_uri } "
764+ )
765+
766+ # Validate the final result
767+ if not registry_uri or not username or not password :
768+ logger .warning (
769+ f"Invalid ImagePullSecret data: registry_uri='{ registry_uri } ', username='{ username } ', password_length={ len (password ) if password else 0 } "
770+ )
771+ return None
772+
773+ logger .debug (
774+ f"Returning ImagePullSecret data: registry='{ registry_uri } ', username='{ username [:3 ]} ***'"
775+ )
776+ return registry_uri , username , password
0 commit comments