code: def _setup_cluster_environment(
      test: Test,
      result: Result,
      cluster_manager: ClusterManager,
      cluster_env_id: Optional[str],
  ) -> Tuple[str, int, int, int, int]:
      setup_signal_handling()
      # Load configs
      cluster_compute = load_test_cluster_compute(test)
  
      if cluster_env_id:
          try:
              cluster_manager.cluster_env_id = cluster_env_id
              cluster_manager.build_cluster_env()
              cluster_manager.fetch_build_info()
              logger.info(
                  "Using overridden cluster environment with ID "
                  f"{cluster_env_id} and build ID "
                  f"{cluster_manager.cluster_env_build_id}"
              )
          except Exception as e:
              raise ClusterEnvCreateError(
                  f"Could not get existing overridden cluster environment "
                  f"{cluster_env_id}: {e}"
              ) from e
      else:
          cluster_manager.set_cluster_env()
  
      # Load some timeouts
      build_timeout = int(
          test["run"].get("build_timeout", DEFAULT_BUILD_TIMEOUT)
      )
      command_timeout = int(
          test["run"].get("timeout", DEFAULT_COMMAND_TIMEOUT)
      )
      cluster_timeout = int(
          test["run"].get("session_timeout", DEFAULT_CLUSTER_TIMEOUT)
      )
  
      # Get prepare command timeout, if any
      prepare_cmd = test["run"].get("prepare", None)
      if prepare_cmd:
          prepare_timeout = test["run"].get(
              "prepare_timeout", command_timeout
          )
      else:
          prepare_timeout = 0
  
      # Base maximum uptime on the combined command and prepare timeouts
      command_and_prepare_timeout = command_timeout + prepare_timeout
  
      # Use default timeout = 0 here if wait_for_nodes is empty. This is to make
      # sure we don't inflate the maximum_uptime_minutes too much if we don't wait
      # for nodes at all.
      # The actual default will be otherwise loaded further down.
      wait_timeout = int(
          test["run"].get("wait_for_nodes", {}).get("timeout", 0)
      )
  
      autosuspend_mins = test["cluster"].get("autosuspend_mins", None)
      if autosuspend_mins:
          cluster_manager.autosuspend_minutes = autosuspend_mins
          autosuspend_base = autosuspend_mins
      else:
          cluster_manager.autosuspend_minutes = min(
              DEFAULT_AUTOSUSPEND_MINS,
              int(command_and_prepare_timeout / 60)
              + TIMEOUT_BUFFER_MINUTES,
          )
          # Maximum uptime should be based on the command timeout, not the
          # DEFAULT_AUTOSUSPEND_MINS
          autosuspend_base = (
              int(command_and_prepare_timeout / 60)
              + TIMEOUT_BUFFER_MINUTES
          )
  
      maximum_uptime_minutes = test["cluster"].get(
          "maximum_uptime_minutes", None
      )
      if maximum_uptime_minutes:
          cluster_manager.maximum_uptime_minutes = (
              maximum_uptime_minutes
          )
      else:
          cluster_manager.maximum_uptime_minutes = (
              autosuspend_base + wait_timeout + TIMEOUT_BUFFER_MINUTES
          )
  
      # Set cluster compute here. Note that this may use timeouts provided
      # above.
      cluster_manager.set_cluster_compute(
          cluster_compute,
          extra_tags=result.extra_tags,
      )
  
      return (
          prepare_cmd,
          prepare_timeout,
          build_timeout,
          cluster_timeout,
          command_timeout,
      )
  
imports: import os
  import time
  import traceback
  from typing import Optional, List, Tuple
  from ray_release.alerts.handle import handle_result, require_result
  from ray_release.anyscale_util import get_cluster_name
  from ray_release.buildkite.output import buildkite_group, buildkite_open_last
  from ray_release.cluster_manager.cluster_manager import ClusterManager
  from ray_release.cluster_manager.full import FullClusterManager
  from ray_release.cluster_manager.minimal import MinimalClusterManager
  from ray_release.command_runner.job_runner import JobRunner
  from ray_release.command_runner.command_runner import CommandRunner
  from ray_release.command_runner.anyscale_job_runner import AnyscaleJobRunner
  from ray_release.test import Test
  from ray_release.config import DEFAULT_BUILD_TIMEOUT, DEFAULT_CLUSTER_TIMEOUT, DEFAULT_COMMAND_TIMEOUT, DEFAULT_WAIT_FOR_NODES_TIMEOUT, RELEASE_PACKAGE_DIR, DEFAULT_AUTOSUSPEND_MINS
  from ray_release.template import load_test_cluster_compute
  from ray_release.exception import ReleaseTestConfigError, ReleaseTestSetupError, CommandError, PrepareCommandError, CommandTimeout, PrepareCommandTimeout, TestCommandError, TestCommandTimeout, ClusterEnvCreateError
  from ray_release.file_manager.job_file_manager import JobFileManager
  from ray_release.logger import logger
  from ray_release.reporter.reporter import Reporter
  from ray_release.result import Result, ResultStatus, handle_exception
  from ray_release.signal_handling import setup_signal_handling, reset_signal_handling, register_handler
label_desc: Use image node_id 3 for calling a global function with example usage: _setup_cluster_environment(test, result, cluster_manager, cluster_env_id) and returns: prepare_cmd,  prepare_timeout,  build_timeout,  cluster_timeout,  command_timeout