prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [bug] TFJob launcher pipeline task fails when `delete_finished_tfjob` flag is `True`
  https://github.com/kubeflow/pipelines/blob/127dab4d4671849d596c455f4619ea807d22f6ea/components/kubeflow/launcher/component.yaml#L19
  
  When `delete_finished_tfjob` flag is `True`, TFJob launcher task fails with error below.
  
  ```
  Traceback (most recent call last):
    File "/ml/launch_tfjob.py", line 136, in <module>
      main()
    File "/ml/launch_tfjob.py", line 133, in main
      tfjob.delete(args.name, args.namespace)
    File "/ml/launch_crd.py", line 115, in delete
      body)
  TypeError: delete_namespaced_custom_object() takes exactly 6 arguments (7 given)
  ```
  
  I think it's some kind of kubernetes client SDK version issue in `nikenano/launchernew:latest` container image.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `components/kubeflow/common/launch_crd.py`
  Content:
  ```
  1 # Copyright 2019 kubeflow.org.
  2 # Licensed under the Apache License, Version 2.0 (the "License");
  3 # you may not use this file except in compliance with the License.
  4 # You may obtain a copy of the License at
  5 #
  6 #      http://www.apache.org/licenses/LICENSE-2.0
  7 #
  8 # Unless required by applicable law or agreed to in writing, software
  9 # distributed under the License is distributed on an "AS IS" BASIS,
  10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11 # See the License for the specific language governing permissions and
  12 # limitations under the License.
  13 
  14 import datetime
  15 import json
  16 import logging
  17 import multiprocessing
  18 import time
  19 
  20 from kubernetes import client as k8s_client
  21 from kubernetes.client import rest
  22 
  23 logger = logging.getLogger(__name__)
  24 
  25 class K8sCR(object):
  26   def __init__(self, group, plural, version, client):
  27     self.group = group
  28     self.plural = plural
  29     self.version = version
  30     self.client = k8s_client.CustomObjectsApi(client)
  31 
  32   def wait_for_condition(self,
  33                          namespace,
  34                          name,
  35                          expected_conditions=[],
  36                          timeout=datetime.timedelta(days=365),
  37                          polling_interval=datetime.timedelta(seconds=30),
  38                          status_callback=None):
  39     """Waits until any of the specified conditions occur.
  40     Args:
  41       namespace: namespace for the CR.
  42       name: Name of the CR.
  43       expected_conditions: A list of conditions. Function waits until any of the
  44         supplied conditions is reached.
  45       timeout: How long to wait for the CR.
  46       polling_interval: How often to poll for the status of the CR.
  47       status_callback: (Optional): Callable. If supplied this callable is
  48         invoked after we poll the CR. Callable takes a single argument which
  49         is the CR.
  50     """
  51     end_time = datetime.datetime.now() + timeout
  52     while True:
  53       try:
  54         results = self.client.get_namespaced_custom_object(
  55           self.group, self.version, namespace, self.plural, name)
  56       except Exception as e:
  57         logger.error("There was a problem waiting for %s/%s %s in namespace %s; Exception: %s",
  58                        self.group, self.plural, name, namespace, e)
  59         raise
  60 
  61       if results:
  62         if status_callback:
  63           status_callback(results)
  64         expected, condition = self.is_expected_conditions(results, expected_conditions)
  65         if expected:
  66           logger.info("%s/%s %s in namespace %s has reached the expected condition: %s.",
  67                        self.group, self.plural, name, namespace, condition)
  68           return results
  69         else:
  70           if condition:
  71             logger.info("Current condition of %s/%s %s in namespace %s is %s.",
  72                   self.group, self.plural, name, namespace, condition)
  73 
  74       if datetime.datetime.now() + polling_interval > end_time:
  75         raise Exception(
  76           "Timeout waiting for {0}/{1} {2} in namespace {3} to enter one of the "
  77           "conditions {4}.".format(self.group, self.plural, name, namespace, expected_conditions))
  78 
  79       time.sleep(polling_interval.seconds)
  80 
  81   def is_expected_conditions(self, inst, expected_conditions):
  82       conditions = inst.get('status', {}).get("conditions")
  83       if not conditions:
  84           return False, ""
  85       if conditions[-1]["type"] in expected_conditions and conditions[-1]["status"] == "True":
  86           return True, conditions[-1]["type"]
  87       else:
  88           return False, conditions[-1]["type"]
  89 
  90   def create(self, spec):
  91     """Create a CR.
  92     Args:
  93       spec: The spec for the CR.
  94     """
  95     try:
  96       # Create a Resource
  97       namespace = spec["metadata"].get("namespace", "default")
  98       logger.info("Creating %s/%s %s in namespace %s.",
  99         self.group, self.plural, spec["metadata"]["name"], namespace)
  100       api_response = self.client.create_namespaced_custom_object(
  101         self.group, self.version, namespace, self.plural, spec)
  102       logger.info("Created %s/%s %s in namespace %s.",
  103         self.group, self.plural, spec["metadata"]["name"], namespace)
  104       return api_response
  105     except rest.ApiException as e:
  106       self._log_and_raise_exception(e, "create")
  107 
  108   def delete(self, name, namespace):
  109     try:
  110       body = {
  111         # Set garbage collection so that CR won't be deleted until all
  112         # owned references are deleted.
  113         "propagationPolicy": "Foreground",
  114       }
  115       logger.info("Deleteing %s/%s %s in namespace %s.",
  116         self.group, self.plural, name, namespace)
  117       api_response = self.client.delete_namespaced_custom_object(
  118         self.group,
  119         self.version,
  120         namespace,
  121         self.plural,
  122         name,
  123         body)
  124       logger.info("Deleted %s/%s %s in namespace %s.",
  125         self.group, self.plural, name, namespace)
  126       return api_response
  127     except rest.ApiException as e:
  128       self._log_and_raise_exception(e, "delete")
  129 
  130   def _log_and_raise_exception(self, ex, action):
  131     message = ""
  132     if ex.message:
  133       message = ex.message
  134     if ex.body:
  135       try:
  136         body = json.loads(ex.body)
  137         message = body.get("message")
  138       except ValueError:
  139         logger.error("Exception when %s %s/%s: %s", action, self.group, self.plural, ex.body)
  140         raise
  141 
  142     logger.error("Exception when %s %s/%s: %s", action, self.group, self.plural, ex.body)
  143     raise ex
  144 
  145
  ```
  --- 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/components/kubeflow/common/launch_crd.py b/components/kubeflow/common/launch_crd.py
  --- a/components/kubeflow/common/launch_crd.py
  +++ b/components/kubeflow/common/launch_crd.py
  @@ -115,12 +115,12 @@
         logger.info("Deleteing %s/%s %s in namespace %s.",
           self.group, self.plural, name, namespace)
         api_response = self.client.delete_namespaced_custom_object(
  -        self.group,
  -        self.version,
  -        namespace,
  -        self.plural,
  -        name,
  -        body)
  +        group=self.group,
  +        version=self.version,
  +        namespace=namespace,
  +        plural=self.plural,
  +        name=name,
  +        body=body)
         logger.info("Deleted %s/%s %s in namespace %s.",
           self.group, self.plural, name, namespace)
         return api_response
  
verification_info: {"golden_diff": "diff --git a/components/kubeflow/common/launch_crd.py b/components/kubeflow/common/launch_crd.py\n--- a/components/kubeflow/common/launch_crd.py\n+++ b/components/kubeflow/common/launch_crd.py\n@@ -115,12 +115,12 @@\n       logger.info(\"Deleteing %s/%s %s in namespace %s.\",\n         self.group, self.plural, name, namespace)\n       api_response = self.client.delete_namespaced_custom_object(\n-        self.group,\n-        self.version,\n-        namespace,\n-        self.plural,\n-        name,\n-        body)\n+        group=self.group,\n+        version=self.version,\n+        namespace=namespace,\n+        plural=self.plural,\n+        name=name,\n+        body=body)\n       logger.info(\"Deleted %s/%s %s in namespace %s.\",\n         self.group, self.plural, name, namespace)\n       return api_response\n", "issue": "[bug] TFJob launcher pipeline task fails when `delete_finished_tfjob` flag is `True`\nhttps://github.com/kubeflow/pipelines/blob/127dab4d4671849d596c455f4619ea807d22f6ea/components/kubeflow/launcher/component.yaml#L19\r\n\r\nWhen `delete_finished_tfjob` flag is `True`, TFJob launcher task fails with error below.\r\n\r\n```\r\nTraceback (most recent call last):\r\n  File \"/ml/launch_tfjob.py\", line 136, in <module>\r\n    main()\r\n  File \"/ml/launch_tfjob.py\", line 133, in main\r\n    tfjob.delete(args.name, args.namespace)\r\n  File \"/ml/launch_crd.py\", line 115, in delete\r\n    body)\r\nTypeError: delete_namespaced_custom_object() takes exactly 6 arguments (7 given)\r\n```\r\n\r\nI think it's some kind of kubernetes client SDK version issue in `nikenano/launchernew:latest` container image.\n", "before_files": [{"content": "# Copyright 2019 kubeflow.org.\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport datetime\nimport json\nimport logging\nimport multiprocessing\nimport time\n\nfrom kubernetes import client as k8s_client\nfrom kubernetes.client import rest\n\nlogger = logging.getLogger(__name__)\n\nclass K8sCR(object):\n  def __init__(self, group, plural, version, client):\n    self.group = group\n    self.plural = plural\n    self.version = version\n    self.client = k8s_client.CustomObjectsApi(client)\n\n  def wait_for_condition(self,\n                         namespace,\n                         name,\n                         expected_conditions=[],\n                         timeout=datetime.timedelta(days=365),\n                         polling_interval=datetime.timedelta(seconds=30),\n                         status_callback=None):\n    \"\"\"Waits until any of the specified conditions occur.\n    Args:\n      namespace: namespace for the CR.\n      name: Name of the CR.\n      expected_conditions: A list of conditions. Function waits until any of the\n        supplied conditions is reached.\n      timeout: How long to wait for the CR.\n      polling_interval: How often to poll for the status of the CR.\n      status_callback: (Optional): Callable. If supplied this callable is\n        invoked after we poll the CR. Callable takes a single argument which\n        is the CR.\n    \"\"\"\n    end_time = datetime.datetime.now() + timeout\n    while True:\n      try:\n        results = self.client.get_namespaced_custom_object(\n          self.group, self.version, namespace, self.plural, name)\n      except Exception as e:\n        logger.error(\"There was a problem waiting for %s/%s %s in namespace %s; Exception: %s\",\n                       self.group, self.plural, name, namespace, e)\n        raise\n\n      if results:\n        if status_callback:\n          status_callback(results)\n        expected, condition = self.is_expected_conditions(results, expected_conditions)\n        if expected:\n          logger.info(\"%s/%s %s in namespace %s has reached the expected condition: %s.\",\n                       self.group, self.plural, name, namespace, condition)\n          return results\n        else:\n          if condition:\n            logger.info(\"Current condition of %s/%s %s in namespace %s is %s.\",\n                  self.group, self.plural, name, namespace, condition)\n\n      if datetime.datetime.now() + polling_interval > end_time:\n        raise Exception(\n          \"Timeout waiting for {0}/{1} {2} in namespace {3} to enter one of the \"\n          \"conditions {4}.\".format(self.group, self.plural, name, namespace, expected_conditions))\n\n      time.sleep(polling_interval.seconds)\n\n  def is_expected_conditions(self, inst, expected_conditions):\n      conditions = inst.get('status', {}).get(\"conditions\")\n      if not conditions:\n          return False, \"\"\n      if conditions[-1][\"type\"] in expected_conditions and conditions[-1][\"status\"] == \"True\":\n          return True, conditions[-1][\"type\"]\n      else:\n          return False, conditions[-1][\"type\"]\n\n  def create(self, spec):\n    \"\"\"Create a CR.\n    Args:\n      spec: The spec for the CR.\n    \"\"\"\n    try:\n      # Create a Resource\n      namespace = spec[\"metadata\"].get(\"namespace\", \"default\")\n      logger.info(\"Creating %s/%s %s in namespace %s.\",\n        self.group, self.plural, spec[\"metadata\"][\"name\"], namespace)\n      api_response = self.client.create_namespaced_custom_object(\n        self.group, self.version, namespace, self.plural, spec)\n      logger.info(\"Created %s/%s %s in namespace %s.\",\n        self.group, self.plural, spec[\"metadata\"][\"name\"], namespace)\n      return api_response\n    except rest.ApiException as e:\n      self._log_and_raise_exception(e, \"create\")\n\n  def delete(self, name, namespace):\n    try:\n      body = {\n        # Set garbage collection so that CR won't be deleted until all\n        # owned references are deleted.\n        \"propagationPolicy\": \"Foreground\",\n      }\n      logger.info(\"Deleteing %s/%s %s in namespace %s.\",\n        self.group, self.plural, name, namespace)\n      api_response = self.client.delete_namespaced_custom_object(\n        self.group,\n        self.version,\n        namespace,\n        self.plural,\n        name,\n        body)\n      logger.info(\"Deleted %s/%s %s in namespace %s.\",\n        self.group, self.plural, name, namespace)\n      return api_response\n    except rest.ApiException as e:\n      self._log_and_raise_exception(e, \"delete\")\n\n  def _log_and_raise_exception(self, ex, action):\n    message = \"\"\n    if ex.message:\n      message = ex.message\n    if ex.body:\n      try:\n        body = json.loads(ex.body)\n        message = body.get(\"message\")\n      except ValueError:\n        logger.error(\"Exception when %s %s/%s: %s\", action, self.group, self.plural, ex.body)\n        raise\n\n    logger.error(\"Exception when %s %s/%s: %s\", action, self.group, self.plural, ex.body)\n    raise ex\n\n", "path": "components/kubeflow/common/launch_crd.py"}], "after_files": [{"content": "# Copyright 2019 kubeflow.org.\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport datetime\nimport json\nimport logging\nimport multiprocessing\nimport time\n\nfrom kubernetes import client as k8s_client\nfrom kubernetes.client import rest\n\nlogger = logging.getLogger(__name__)\n\nclass K8sCR(object):\n  def __init__(self, group, plural, version, client):\n    self.group = group\n    self.plural = plural\n    self.version = version\n    self.client = k8s_client.CustomObjectsApi(client)\n\n  def wait_for_condition(self,\n                         namespace,\n                         name,\n                         expected_conditions=[],\n                         timeout=datetime.timedelta(days=365),\n                         polling_interval=datetime.timedelta(seconds=30),\n                         status_callback=None):\n    \"\"\"Waits until any of the specified conditions occur.\n    Args:\n      namespace: namespace for the CR.\n      name: Name of the CR.\n      expected_conditions: A list of conditions. Function waits until any of the\n        supplied conditions is reached.\n      timeout: How long to wait for the CR.\n      polling_interval: How often to poll for the status of the CR.\n      status_callback: (Optional): Callable. If supplied this callable is\n        invoked after we poll the CR. Callable takes a single argument which\n        is the CR.\n    \"\"\"\n    end_time = datetime.datetime.now() + timeout\n    while True:\n      try:\n        results = self.client.get_namespaced_custom_object(\n          self.group, self.version, namespace, self.plural, name)\n      except Exception as e:\n        logger.error(\"There was a problem waiting for %s/%s %s in namespace %s; Exception: %s\",\n                       self.group, self.plural, name, namespace, e)\n        raise\n\n      if results:\n        if status_callback:\n          status_callback(results)\n        expected, condition = self.is_expected_conditions(results, expected_conditions)\n        if expected:\n          logger.info(\"%s/%s %s in namespace %s has reached the expected condition: %s.\",\n                       self.group, self.plural, name, namespace, condition)\n          return results\n        else:\n          if condition:\n            logger.info(\"Current condition of %s/%s %s in namespace %s is %s.\",\n                  self.group, self.plural, name, namespace, condition)\n\n      if datetime.datetime.now() + polling_interval > end_time:\n        raise Exception(\n          \"Timeout waiting for {0}/{1} {2} in namespace {3} to enter one of the \"\n          \"conditions {4}.\".format(self.group, self.plural, name, namespace, expected_conditions))\n\n      time.sleep(polling_interval.seconds)\n\n  def is_expected_conditions(self, inst, expected_conditions):\n      conditions = inst.get('status', {}).get(\"conditions\")\n      if not conditions:\n          return False, \"\"\n      if conditions[-1][\"type\"] in expected_conditions and conditions[-1][\"status\"] == \"True\":\n          return True, conditions[-1][\"type\"]\n      else:\n          return False, conditions[-1][\"type\"]\n\n  def create(self, spec):\n    \"\"\"Create a CR.\n    Args:\n      spec: The spec for the CR.\n    \"\"\"\n    try:\n      # Create a Resource\n      namespace = spec[\"metadata\"].get(\"namespace\", \"default\")\n      logger.info(\"Creating %s/%s %s in namespace %s.\",\n        self.group, self.plural, spec[\"metadata\"][\"name\"], namespace)\n      api_response = self.client.create_namespaced_custom_object(\n        self.group, self.version, namespace, self.plural, spec)\n      logger.info(\"Created %s/%s %s in namespace %s.\",\n        self.group, self.plural, spec[\"metadata\"][\"name\"], namespace)\n      return api_response\n    except rest.ApiException as e:\n      self._log_and_raise_exception(e, \"create\")\n\n  def delete(self, name, namespace):\n    try:\n      body = {\n        # Set garbage collection so that CR won't be deleted until all\n        # owned references are deleted.\n        \"propagationPolicy\": \"Foreground\",\n      }\n      logger.info(\"Deleteing %s/%s %s in namespace %s.\",\n        self.group, self.plural, name, namespace)\n      api_response = self.client.delete_namespaced_custom_object(\n        group=self.group,\n        version=self.version,\n        namespace=namespace,\n        plural=self.plural,\n        name=name,\n        body=body)\n      logger.info(\"Deleted %s/%s %s in namespace %s.\",\n        self.group, self.plural, name, namespace)\n      return api_response\n    except rest.ApiException as e:\n      self._log_and_raise_exception(e, \"delete\")\n\n  def _log_and_raise_exception(self, ex, action):\n    message = \"\"\n    if ex.message:\n      message = ex.message\n    if ex.body:\n      try:\n        body = json.loads(ex.body)\n        message = body.get(\"message\")\n      except ValueError:\n        logger.error(\"Exception when %s %s/%s: %s\", action, self.group, self.plural, ex.body)\n        raise\n\n    logger.error(\"Exception when %s %s/%s: %s\", action, self.group, self.plural, ex.body)\n    raise ex\n\n", "path": "components/kubeflow/common/launch_crd.py"}]}