def QuarantineGKEWorkload(project_id: str,
                          location: str,
                          cluster_id: str,
                          namespace: str,
                          workload_id: str,
                          exempted_src_ips: Optional[List[str]] = None) -> None:
  """Guides the analyst through quarantining a GKE workload.

  Args:
    project_id (str): The GCP project ID.
    location (str): The region/zone in which the cluster resides.
    cluster_id (str): The name of the Kubernetes cluster holding the workload.
    namespace (str): The Kubernetes namespace of the workload (e.g. 'default').
    workload_id (str): The name of the workload.
    exempted_src_ips (List[str]): Optional. The list of source IPs to exempt
        in the GCP firewall rules when isolating the nodes. If not specified,
        no IPs are exempted.

  Raises:
    ResourceNotFoundError: If the workload isn't found.
  """
  logger.info('Starting GKE quarantining process...')

  cluster = gke.GkeCluster(project_id, location, cluster_id)
  maybe_workload = cluster.FindWorkload(workload_id, namespace)
  if not maybe_workload:
    raise errors.ResourceNotFoundError(
        'Workload not found. Cannot proceed with quarantining process.',
        __name__)
  # If we directly assigned to `workload`, mypy would consider it of type
  # `Optional[K8sWorkload]`, causing type check failures below. Doing it
  # indirectly after the `if not` check allows mypy to infer that `workload`
  # is of type `K8sWorkload`.
  workload = maybe_workload
  logger.info(
      'Workload "{0:s}" in namespace "{1:s}"...'.format(workload_id, namespace))

  workload_nodes = workload.GetCoveredNodes()
  workload_pods = workload.GetCoveredPods()

  def CordonNodes() -> None:
    """Cordons the compromised nodes."""
    for node in workload_nodes:
      logger.info(
          'Cordoning Kubernetes node {0:s} from {1:s} '
          'deployment...'.format(node.name, workload.name))
      node.Cordon()

  def AbandonNodes() -> None:
    """Abandons the nodes from their respective managed instance groups."""
    compute_project = compute.GoogleCloudCompute(project_id)
    groups_by_instance = compute_project.ListMIGSByInstanceName(location)
    for node in workload_nodes:
      if node.name in groups_by_instance:
        logger.info(
            'Abandoning instance {0:s} from respective managed instance '
            'group...'.format(node.name))
        instance = compute_project.GetInstance(node.name)
        instance.AbandonFromMIG(groups_by_instance[instance.name])
      else:
        logger.warning(
            'Could not abandon {0:s} from respective managed instance '
            'group, parent managed instance group not found.'.format(node.name))

  def IsolatePods() -> None:
    """Isolates the pods via Kubernetes NetworkPolicy."""
    logger.info(
        'Creating deny-all NetworkPolicy for {0:s} '
        'workload...'.format(workload_id))
    mitigation.IsolatePodsWithNetworkPolicy(cluster, workload_pods,
                                            existing_policies_prompt=True)

  def DrainNodes() -> None:
    """Drains the workload nodes from other pods."""
    logger.info('Draining workload nodes from other pods...')
    mitigation.DrainWorkloadNodesFromOtherPods(workload, cordon=False)

  def OrphanPods() -> None:
    """Orphans the pods of the workload."""
    logger.info(
        'Orphaning Kubernetes workload {0:s}\'s pods...'.format(workload_id))
    workload.OrphanPods()

  def FirewallNodes() -> None:
    """Puts each node from the workload into network quarantine."""
    for node in workload_nodes:
      logger.info(
          ('Putting instance "{0:s}" from workload "{1:s}" into network'
           ' quarantine...').format(node.name, workload_id))
      InstanceNetworkQuarantine(project_id, node.name,
                                exempted_src_ips=exempted_src_ips)

  # Third prompt options
  isolate_nodes = prompts.PromptOption('Isolate nodes', FirewallNodes)
  isolate_pods = prompts.PromptOption('Isolate pods', IsolatePods)
  isolate_nodes_and_pods = prompts.PromptOption(
      'Isolate nodes and pods', DrainNodes, FirewallNodes)

  # Second prompt options, defined afterwards so that we can link disables
  preserve_delete = prompts.PromptOption(
      'Preserve evidence and delete workload', OrphanPods)
  preserve_preserve = prompts.PromptOption(
      'Preserve evidence and preserve workload',
      # No functions are called when this option is selected, a multi prompt
      # was favored over a yes/no prompt for clarity
      disable_options=[
          (
              isolate_nodes,
              'Isolating nodes will cause workload pods to appear elsewhere.'),
          (
              isolate_nodes_and_pods,
              'Isolating nodes will cause workload pods to appear elsewhere.')
      ])

  prompt_sequence = prompts.PromptSequence(
      prompts.YesNoPrompt(
          prompts.PromptOption(
              'Abandon nodes from managed instance group', AbandonNodes),
          default_yes=True),
      prompts.YesNoPrompt(
          prompts.PromptOption('Cordon nodes', CordonNodes), default_yes=True),
      prompts.MultiPrompt([
          preserve_delete,
          preserve_preserve,
      ]),
      prompts.MultiPrompt([isolate_nodes, isolate_pods,
                           isolate_nodes_and_pods]),
  )

  # If network policy is disabled, disable the isolate_pods prompt because
  # it will raise an error
  if not cluster.IsNetworkPolicyEnabled():
    isolate_pods.Disable('NetworkPolicy not enabled.')

  prompt_sequence.Run(summarize=True)
Guides the analyst through quarantining a GKE workload.

Args:
project_id (str): The GCP project ID.
location (str): The region/zone in which the cluster resides.
cluster_id (str): The name of the Kubernetes cluster holding the workload.
namespace (str): The Kubernetes namespace of the workload (e.g. 'default').
workload_id (str): The name of the workload.
exempted_src_ips (List[str]): Optional. The list of source IPs to exempt
in the GCP firewall rules when isolating the nodes. If not specified,
no IPs are exempted.

Raises:
ResourceNotFoundError: If the workload isn't found.
libcloudforensics/providers/gcp/forensics.py