class_docstr: Docker cluster wrapper.
  
  Creates a directory for starting a fake multinode docker cluster.
  
  Includes APIs to update the cluster config as needed in tests,
  and to start and connect to the cluster.
class_docstr_tok: ["Docker","cluster","wrapper",".","Creates","a","directory","for","starting","a","fake","multinode","docker","cluster",".","Includes","APIs","to","update","the","cluster","config","as","needed","in","tests",",","and","to","start","and","connect","to","the","cluster","."]
docstr: Update autoscaling config.
  
  Does a deep update of the base config with a new configuration.
  This can change autoscaling behavior.
  
  Args:
      config: Partial config to update current
          config with.
code: def update_config(self, config: Optional[Dict[str, Any]] = None):
      """Update autoscaling config.
  
      Does a deep update of the base config with a new configuration.
      This can change autoscaling behavior.
  
      Args:
          config: Partial config to update current
              config with.
  
      """
      assert self._tempdir, "Call setup() first"
  
      config = config or {}
  
      if config:
          self._partial_config = config
  
      if not config.get("provider", {}).get("image"):
          # No image specified, trying to parse from buildkite
          docker_image = os.environ.get("RAY_DOCKER_IMAGE", None)
  
          if not docker_image:
              # If still no docker image, use one according to Python version
              mj = sys.version_info.major
              mi = sys.version_info.minor
  
              docker_image = DEFAULT_DOCKER_IMAGE.format(
                  major=mj, minor=mi
              )
  
          self._docker_image = docker_image
  
      with open(self._base_config_file, "rt") as f:
          cluster_config = yaml.safe_load(f)
  
      if self._partial_config:
          deep_update(
              cluster_config,
              self._partial_config,
              new_keys_allowed=True,
          )
  
      if self._docker_image:
          cluster_config["provider"]["image"] = self._docker_image
  
      cluster_config["provider"]["shared_volume_dir"] = self._tempdir
  
      self._cluster_config = cluster_config
  
      with open(self._config_file, "wt") as f:
          yaml.safe_dump(self._cluster_config, f)
  
      logging.info(f"Updated cluster config to: {self._cluster_config}")
  
imports: import json
  import logging
  import os
  import random
  import shutil
  import subprocess
  import sys
  import tempfile
  import threading
  import time
  from typing import Any, Dict, Optional
  import yaml
  import ray
  from ray._private.dict import deep_update
  from ray.autoscaler._private.fake_multi_node.node_provider import FAKE_DOCKER_DEFAULT_CLIENT_PORT, FAKE_DOCKER_DEFAULT_GCS_PORT
  from ray.util.queue import Empty, Queue
label_desc: Use image node_id 10 for calling the DockerCluster obj's underlying member method code with example usage: obj.update_config(config) without return types