code: def replace_job_spec_image(spec: JobSpec, image_id: str) -> JobSpec:
      """generates a new JobSpec based on an existing one, but replacing the
      image id
  
      Args:
      spec: job spec used as basis
      image_id: new image id
  
      Returns:
      new JobSpec
      """
  
      if spec.platform == Platform.LOCAL:
          return replace_local_job_spec_image(
              spec=spec, image_id=image_id
          )
  
      if spec.platform == Platform.CAIP:
          return replace_caip_job_spec_image(
              spec=spec, image_id=image_id
          )
  
      if spec.platform == Platform.GKE:
          return replace_gke_job_spec_image(
              spec=spec, image_id=image_id
          )
  
      return None
  
imports: import os
  import sys
  from contextlib import contextmanager
  from copy import deepcopy
  from typing import Any, Dict, List, Optional
  from absl import logging
  from blessings import Terminal
  from googleapiclient import discovery
  from sqlalchemy import create_engine
  from sqlalchemy.engine.base import Engine
  from sqlalchemy.exc import OperationalError
  from sqlalchemy.orm import Session, sessionmaker
  import caliban.config.experiment
  import caliban.util.auth
  from caliban.history.types import ContainerSpec, Experiment, ExperimentGroup, Job, JobSpec, JobStatus, Platform, init_db
  from caliban.platform.cloud.types import JobStatus
  from caliban.platform.gke.cluster import Cluster
  from caliban.platform.gke.types import JobStatus
  from caliban.platform.gke.util import default_credentials
label_desc: Use image node_id 20 for calling a global function with example usage: replace_job_spec_image(spec, image_id) and returns: None, replace_local_job_spec_image, replace_caip_job_spec_image, replace_gke_job_spec_image