code: def test_options_update(shutdown_only):
      from ray.workflow.common import WORKFLOW_OPTIONS
  
      # Options are given in decorator first, then in the first .options()
      # and finally in the second .options()
      @workflow.options(task_id="old_name", metadata={"k": "v"})
      @ray.remote(num_cpus=2, max_retries=1)
      def f():
          return
  
      # name is updated from the old name in the decorator to the new name in the first
      # .options(), then preserved in the second options.
      # metadata and ray_options are "updated"
      # max_retries only defined in the decorator and it got preserved all the way
      new_f = f.options(
          num_returns=2,
          **workflow.options(
              task_id="new_name", metadata={"extra_k2": "extra_v2"}
          ),
      )
      options = new_f.bind().get_options()
      assert options == {
          "num_cpus": 2,
          "num_returns": 2,
          "max_retries": 1,
          "_metadata": {
              WORKFLOW_OPTIONS: {
                  "task_id": "new_name",
                  "metadata": {"extra_k2": "extra_v2"},
              }
          },
      }
  
file_path: ray/python/ray/workflow/tests/test_basic_workflows_4.py
imports: import os
  import pytest
  from ray._private.test_utils import run_string_as_driver
  import ray
  from ray import workflow
  from ray.tests.conftest import *
label_desc: Use image node_id 2 for calling a global function with example usage: test_options_update(shutdown_only) without return types