class_docstr: Testing the calls made using GridRestClient to create the app.
class_docstr_tok: ["Testing","the","calls","made","using","GridRestClient","to","create","the","app","."]
code: def test_new_instance_on_different_cluster(
      self, tmpdir, cloud_backend, project_id, old_cluster, new_cluster
  ):
      entrypoint = Path(tmpdir) / "entrypoint.py"
      entrypoint.touch()
  
      app_name = "test-app"
  
      mock_client = mock.MagicMock()
      mock_client.projects_service_list_memberships.return_value = (
          V1ListMembershipsResponse(
              memberships=[
                  V1Membership(
                      name="Default Project", project_id=project_id
                  )
              ]
          )
      )
      mock_client.lightningapp_v2_service_create_lightningapp_release.return_value = V1LightningRun(
          cluster_id=new_cluster
      )
  
      # Note:
      # backend converts "None" cluster to "litng-ai-03"
      # dispatch should receive None, but API calls should return "litng-ai-03"
      mock_client.cluster_service_list_clusters.return_value = (
          V1ListClustersResponse(
              [
                  Externalv1Cluster(id=old_cluster or DEFAULT_CLUSTER),
                  Externalv1Cluster(id=new_cluster or DEFAULT_CLUSTER),
              ]
          )
      )
  
      mock_client.projects_service_list_project_cluster_bindings.return_value = V1ListProjectClusterBindingsResponse(
          clusters=[
              V1ProjectClusterBinding(
                  cluster_id=old_cluster or DEFAULT_CLUSTER
              ),
              V1ProjectClusterBinding(
                  cluster_id=new_cluster or DEFAULT_CLUSTER
              ),
          ]
      )
  
      # Mock all clusters as global clusters
      mock_client.cluster_service_get_cluster.side_effect = (
          lambda cluster_id: V1GetClusterResponse(
              id=cluster_id,
              spec=V1ClusterSpec(cluster_type=V1ClusterType.GLOBAL),
          )
      )
  
      cloud_backend.client = mock_client
  
      app = mock.MagicMock()
      app.flows = []
      app.frontend = {}
  
      existing_app = MagicMock()
      existing_app.name = app_name
      existing_app.id = "test-id"
      mock_client.cloud_space_service_list_cloud_spaces.return_value = (
          V1ListCloudSpacesResponse(cloudspaces=[existing_app])
      )
  
      existing_instance = MagicMock()
      existing_instance.name = app_name
      existing_instance.status.phase = (
          V1LightningappInstanceState.STOPPED
      )
      existing_instance.spec.cluster_id = old_cluster or DEFAULT_CLUSTER
      mock_client.lightningapp_instance_service_list_lightningapp_instances.return_value = V1ListLightningappInstancesResponse(
          lightningapps=[existing_instance]
      )
  
      cloud_runtime = cloud.CloudRuntime(app=app, entrypoint=entrypoint)
      cloud_runtime._check_uploaded_folder = mock.MagicMock()
  
      # This is the main assertion:
      # we have an existing instance on `cluster-001`
      # but we want to run this app on `cluster-002`
      cloud_runtime.dispatch(name=app_name, cluster_id=new_cluster)
  
      if new_cluster != old_cluster and None not in (
          old_cluster,
          new_cluster,
      ):
          # If we switched cluster, check that a new name was used which starts with the old name
          mock_client.cloud_space_service_create_lightning_run_instance.assert_called_once()
          args = (
              mock_client.cloud_space_service_create_lightning_run_instance.call_args
          )
          assert args[1]["body"].name != app_name
          assert args[1]["body"].name.startswith(app_name)
          assert args[1]["body"].cluster_id == new_cluster
  
imports: import contextlib
  import logging
  import os
  import pathlib
  import re
  import sys
  from copy import copy
  from pathlib import Path
  from unittest import mock
  from unittest.mock import MagicMock
  import pytest
  from lightning.app import BuildConfig, LightningApp, LightningFlow, LightningWork
  from lightning.app.runners import CloudRuntime, backends, cloud
  from lightning.app.source_code.copytree import _copytree, _parse_lightningignore
  from lightning.app.source_code.local import LocalSourceCodeDir
  from lightning.app.storage import Drive, Mount
  from lightning.app.testing.helpers import EmptyWork
  from lightning.app.utilities.cloud import _get_project
  from lightning.app.utilities.dependency_caching import get_hash
  from lightning.app.utilities.packaging.cloud_compute import CloudCompute
  from lightning_cloud.openapi import CloudspaceIdRunsBody, Externalv1Cluster, Externalv1LightningappInstance, Gridv1ImageSpec, IdGetBody1, ProjectIdProjectclustersbindingsBody, V1BuildSpec, V1CloudSpace, V1CloudSpaceInstanceConfig, V1ClusterSpec, V1ClusterType, V1DataConnectionMount, V1DependencyFileInfo, V1Drive, V1DriveSpec, V1DriveStatus, V1DriveType, V1EnvVar, V1GetClusterResponse, V1GetUserResponse, V1LightningappInstanceSpec, V1LightningappInstanceState, V1LightningappInstanceStatus, V1LightningAuth, V1LightningBasicAuth, V1LightningRun, V1LightningworkDrives, V1LightningworkSpec, V1ListCloudSpacesResponse, V1ListClustersResponse, V1ListLightningappInstancesResponse, V1ListMembershipsResponse, V1ListProjectClusterBindingsResponse, V1Membership, V1Metadata, V1NetworkConfig, V1PackageManager, V1ProjectClusterBinding, V1PythonDependencyInfo, V1QueueServerType, V1SourceType, V1UserFeatures, V1UserRequestedComputeConfig, V1UserRequestedFlowComputeConfig, V1Work
label_desc: Use image node_id 2 for calling the TestAppCreationClient obj's underlying member method code with example usage: obj.test_new_instance_on_different_cluster(tmpdir, cloud_backend, project_id, old_cluster, new_cluster) without return types