prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Provide default gpu resource name and validation
  Currently users can only pass "gpu" as part of the resource name. However, k8s requires it to be either `"nvidia.com/gpu"` or `"amd.com/gpu"` if AMD plugin is enabled. There are other different vendors as well but a pattern to use for validation would be `"<vendor>.com/gpu"`.
  
  We should consider adding `"nvidia.com/gpu"` as the default and validate for user provided gpu resource name based on the pattern `"<vendor>.com/gpu"`.
  
  Reference: https://kubernetes.io/docs/tasks/manage-gpus/scheduling-gpus/
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `elasticdl/python/elasticdl/common/k8s_utils.py`
  Content:
  ```
  1 import re
  2 
  3 
  4 _ALLOWED_RESOURCE_TYPES = ["memory", "disk", "ephemeral-storage", "cpu", "gpu"]
  5 
  6 
  7 def _is_numeric(n):
  8     try:
  9         float(n)
  10     except ValueError:
  11         return False
  12     return True
  13 
  14 
  15 def _valid_gpu_spec(gpu_str):
  16     if not gpu_str.isnumeric():
  17         raise ValueError("invalid gpu request spec: " + gpu_str)
  18     return gpu_str
  19 
  20 
  21 def _valid_cpu_spec(cpu_str):
  22     regexp = re.compile("([1-9]{1})([0-9]*)m$")
  23     if not regexp.match(cpu_str) and not _is_numeric(cpu_str):
  24         raise ValueError("invalid cpu request spec: " + cpu_str)
  25     return cpu_str
  26 
  27 
  28 def _valid_mem_spec(mem_str):
  29     regexp = re.compile("([1-9]{1})([0-9]*)(E|P|T|G|M|K|Ei|Pi|Ti|Gi|Mi|Ki)$")
  30     if not regexp.match(mem_str):
  31         raise ValueError("invalid memory request spec: " + mem_str)
  32     return mem_str
  33 
  34 
  35 def parse_resource(resource_str):
  36     """Parse combined k8s resource string into a dict.
  37 
  38     Args:
  39         resource_str: The string representation for k8s resource,
  40             e.g. "cpu=250m,memory=32Mi,disk=64Mi,gpu=1,ephemeral-storage=32Mi".
  41 
  42     Return:
  43         A Python dictionary parsed from the given resource string.
  44     """
  45     kvs = resource_str.split(",")
  46     resource_names = []
  47     parsed_res_dict = {}
  48     for kv in kvs:
  49         k, v = kv.split("=")
  50         if k not in resource_names:
  51             resource_names.append(k)
  52         else:
  53             raise ValueError(
  54                 "The resource string contains duplicate resource names: %s" % k
  55             )
  56         if k in ["memory", "disk", "ephemeral-storage"]:
  57             _valid_mem_spec(v)
  58         elif k == "cpu":
  59             _valid_cpu_spec(v)
  60         elif k == "gpu":
  61             _valid_gpu_spec(v)
  62         else:
  63             raise ValueError(
  64                 "%s is not in the allowed list of resource types: %s"
  65                 % (k, _ALLOWED_RESOURCE_TYPES)
  66             )
  67         parsed_res_dict[k] = v
  68     return parsed_res_dict
  69
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/elasticdl/python/elasticdl/common/k8s_utils.py b/elasticdl/python/elasticdl/common/k8s_utils.py
  --- a/elasticdl/python/elasticdl/common/k8s_utils.py
  +++ b/elasticdl/python/elasticdl/common/k8s_utils.py
  @@ -2,6 +2,10 @@
   
   
   _ALLOWED_RESOURCE_TYPES = ["memory", "disk", "ephemeral-storage", "cpu", "gpu"]
  +# Any domain name is (syntactically) valid if it's a dot-separated list of
  +# identifiers, each no longer than 63 characters, and made up of letters,
  +# digits and dashes (no underscores).
  +_GPU_VENDOR_REGEX_STR = r"^[a-zA-Z\d-]{,63}(\.[a-zA-Z\d-]{,63})*/gpu$"
   
   
   def _is_numeric(n):
  @@ -57,7 +61,14 @@
               _valid_mem_spec(v)
           elif k == "cpu":
               _valid_cpu_spec(v)
  -        elif k == "gpu":
  +        elif "gpu" in k:
  +            if k == "gpu":
  +                k = "nvidia.com/gpu"
  +            elif not re.compile(_GPU_VENDOR_REGEX_STR).match(k):
  +                raise ValueError(
  +                    "gpu resource name does not have a valid vendor name: %s"
  +                    % k
  +                )
               _valid_gpu_spec(v)
           else:
               raise ValueError(
  
verification_info: {"golden_diff": "diff --git a/elasticdl/python/elasticdl/common/k8s_utils.py b/elasticdl/python/elasticdl/common/k8s_utils.py\n--- a/elasticdl/python/elasticdl/common/k8s_utils.py\n+++ b/elasticdl/python/elasticdl/common/k8s_utils.py\n@@ -2,6 +2,10 @@\n \n \n _ALLOWED_RESOURCE_TYPES = [\"memory\", \"disk\", \"ephemeral-storage\", \"cpu\", \"gpu\"]\n+# Any domain name is (syntactically) valid if it's a dot-separated list of\n+# identifiers, each no longer than 63 characters, and made up of letters,\n+# digits and dashes (no underscores).\n+_GPU_VENDOR_REGEX_STR = r\"^[a-zA-Z\\d-]{,63}(\\.[a-zA-Z\\d-]{,63})*/gpu$\"\n \n \n def _is_numeric(n):\n@@ -57,7 +61,14 @@\n             _valid_mem_spec(v)\n         elif k == \"cpu\":\n             _valid_cpu_spec(v)\n-        elif k == \"gpu\":\n+        elif \"gpu\" in k:\n+            if k == \"gpu\":\n+                k = \"nvidia.com/gpu\"\n+            elif not re.compile(_GPU_VENDOR_REGEX_STR).match(k):\n+                raise ValueError(\n+                    \"gpu resource name does not have a valid vendor name: %s\"\n+                    % k\n+                )\n             _valid_gpu_spec(v)\n         else:\n             raise ValueError(\n", "issue": "Provide default gpu resource name and validation\nCurrently users can only pass \"gpu\" as part of the resource name. However, k8s requires it to be either `\"nvidia.com/gpu\"` or `\"amd.com/gpu\"` if AMD plugin is enabled. There are other different vendors as well but a pattern to use for validation would be `\"<vendor>.com/gpu\"`.\r\n\r\nWe should consider adding `\"nvidia.com/gpu\"` as the default and validate for user provided gpu resource name based on the pattern `\"<vendor>.com/gpu\"`.\r\n\r\nReference: https://kubernetes.io/docs/tasks/manage-gpus/scheduling-gpus/\n", "before_files": [{"content": "import re\n\n\n_ALLOWED_RESOURCE_TYPES = [\"memory\", \"disk\", \"ephemeral-storage\", \"cpu\", \"gpu\"]\n\n\ndef _is_numeric(n):\n    try:\n        float(n)\n    except ValueError:\n        return False\n    return True\n\n\ndef _valid_gpu_spec(gpu_str):\n    if not gpu_str.isnumeric():\n        raise ValueError(\"invalid gpu request spec: \" + gpu_str)\n    return gpu_str\n\n\ndef _valid_cpu_spec(cpu_str):\n    regexp = re.compile(\"([1-9]{1})([0-9]*)m$\")\n    if not regexp.match(cpu_str) and not _is_numeric(cpu_str):\n        raise ValueError(\"invalid cpu request spec: \" + cpu_str)\n    return cpu_str\n\n\ndef _valid_mem_spec(mem_str):\n    regexp = re.compile(\"([1-9]{1})([0-9]*)(E|P|T|G|M|K|Ei|Pi|Ti|Gi|Mi|Ki)$\")\n    if not regexp.match(mem_str):\n        raise ValueError(\"invalid memory request spec: \" + mem_str)\n    return mem_str\n\n\ndef parse_resource(resource_str):\n    \"\"\"Parse combined k8s resource string into a dict.\n\n    Args:\n        resource_str: The string representation for k8s resource,\n            e.g. \"cpu=250m,memory=32Mi,disk=64Mi,gpu=1,ephemeral-storage=32Mi\".\n\n    Return:\n        A Python dictionary parsed from the given resource string.\n    \"\"\"\n    kvs = resource_str.split(\",\")\n    resource_names = []\n    parsed_res_dict = {}\n    for kv in kvs:\n        k, v = kv.split(\"=\")\n        if k not in resource_names:\n            resource_names.append(k)\n        else:\n            raise ValueError(\n                \"The resource string contains duplicate resource names: %s\" % k\n            )\n        if k in [\"memory\", \"disk\", \"ephemeral-storage\"]:\n            _valid_mem_spec(v)\n        elif k == \"cpu\":\n            _valid_cpu_spec(v)\n        elif k == \"gpu\":\n            _valid_gpu_spec(v)\n        else:\n            raise ValueError(\n                \"%s is not in the allowed list of resource types: %s\"\n                % (k, _ALLOWED_RESOURCE_TYPES)\n            )\n        parsed_res_dict[k] = v\n    return parsed_res_dict\n", "path": "elasticdl/python/elasticdl/common/k8s_utils.py"}], "after_files": [{"content": "import re\n\n\n_ALLOWED_RESOURCE_TYPES = [\"memory\", \"disk\", \"ephemeral-storage\", \"cpu\", \"gpu\"]\n# Any domain name is (syntactically) valid if it's a dot-separated list of\n# identifiers, each no longer than 63 characters, and made up of letters,\n# digits and dashes (no underscores).\n_GPU_VENDOR_REGEX_STR = r\"^[a-zA-Z\\d-]{,63}(\\.[a-zA-Z\\d-]{,63})*/gpu$\"\n\n\ndef _is_numeric(n):\n    try:\n        float(n)\n    except ValueError:\n        return False\n    return True\n\n\ndef _valid_gpu_spec(gpu_str):\n    if not gpu_str.isnumeric():\n        raise ValueError(\"invalid gpu request spec: \" + gpu_str)\n    return gpu_str\n\n\ndef _valid_cpu_spec(cpu_str):\n    regexp = re.compile(\"([1-9]{1})([0-9]*)m$\")\n    if not regexp.match(cpu_str) and not _is_numeric(cpu_str):\n        raise ValueError(\"invalid cpu request spec: \" + cpu_str)\n    return cpu_str\n\n\ndef _valid_mem_spec(mem_str):\n    regexp = re.compile(\"([1-9]{1})([0-9]*)(E|P|T|G|M|K|Ei|Pi|Ti|Gi|Mi|Ki)$\")\n    if not regexp.match(mem_str):\n        raise ValueError(\"invalid memory request spec: \" + mem_str)\n    return mem_str\n\n\ndef parse_resource(resource_str):\n    \"\"\"Parse combined k8s resource string into a dict.\n\n    Args:\n        resource_str: The string representation for k8s resource,\n            e.g. \"cpu=250m,memory=32Mi,disk=64Mi,gpu=1,ephemeral-storage=32Mi\".\n\n    Return:\n        A Python dictionary parsed from the given resource string.\n    \"\"\"\n    kvs = resource_str.split(\",\")\n    resource_names = []\n    parsed_res_dict = {}\n    for kv in kvs:\n        k, v = kv.split(\"=\")\n        if k not in resource_names:\n            resource_names.append(k)\n        else:\n            raise ValueError(\n                \"The resource string contains duplicate resource names: %s\" % k\n            )\n        if k in [\"memory\", \"disk\", \"ephemeral-storage\"]:\n            _valid_mem_spec(v)\n        elif k == \"cpu\":\n            _valid_cpu_spec(v)\n        elif \"gpu\" in k:\n            if k == \"gpu\":\n                k = \"nvidia.com/gpu\"\n            elif not re.compile(_GPU_VENDOR_REGEX_STR).match(k):\n                raise ValueError(\n                    \"gpu resource name does not have a valid vendor name: %s\"\n                    % k\n                )\n            _valid_gpu_spec(v)\n        else:\n            raise ValueError(\n                \"%s is not in the allowed list of resource types: %s\"\n                % (k, _ALLOWED_RESOURCE_TYPES)\n            )\n        parsed_res_dict[k] = v\n    return parsed_res_dict\n", "path": "elasticdl/python/elasticdl/common/k8s_utils.py"}]}