We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
build_python_component does not work in KF 6.2 
compiler.build_python_component uses the default name space for pod creation. As of KF 6.2 the notebooks are running under a user name space( ex kubeflow-<username>) with editor service account. This service account does not have access to default kubeflow name space by design. 

SDK needs to be updated to use the user service account instead. 

sample error: 

`HTTP response body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"pods is forbidden: User \"system:serviceaccount:kubeflow-chavoshi:default-editor\" cannot create resource \"pods\" in API group \"\" in the namespace \"kubeflow\"","reason":"Forbidden","details":{"kind":"pods"},"code":403}
`
screen shot: 
https://screenshot.googleplex.com/QotFfe0hgnW.png 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sdk/python/kfp/containers/_component_builder.py`
Content:
```
1 # Copyright 2018 Google LLC
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 import os
16 import inspect
17 import re
18 import sys
19 import tempfile
20 import logging
21 import shutil
22 from collections import OrderedDict
23 from pathlib import Path
24 from typing import Callable
25 from ..components._components import _create_task_factory_from_component_spec
26 from ..components._python_op import _func_to_component_spec
27 from ..components._yaml_utils import dump_yaml
28 from ._container_builder import ContainerBuilder
29 
30 class VersionedDependency(object):
31   """ DependencyVersion specifies the versions """
32   def __init__(self, name, version=None, min_version=None, max_version=None):
33     """ if version is specified, no need for min_version or max_version;
34      if both are specified, version is adopted """
35     self._name = name
36     if version is not None:
37       self._min_version = version
38       self._max_version = version
39     else:
40       self._min_version = min_version
41       self._max_version = max_version
42 
43   @property
44   def name(self):
45     return self._name
46 
47   @property
48   def min_version(self):
49     return self._min_version
50 
51   @min_version.setter
52   def min_version(self, min_version):
53     self._min_version = min_version
54 
55   def has_min_version(self):
56     return self._min_version != None
57 
58   @property
59   def max_version(self):
60     return self._max_version
61 
62   @max_version.setter
63   def max_version(self, max_version):
64     self._max_version = max_version
65 
66   def has_max_version(self):
67     return self._max_version != None
68 
69   def has_versions(self):
70     return (self.has_min_version()) or (self.has_max_version())
71 
72 class DependencyHelper(object):
73   """ DependencyHelper manages software dependency information """
74   def __init__(self):
75     self._PYTHON_PACKAGE = 'PYTHON_PACKAGE'
76     self._dependency = {self._PYTHON_PACKAGE:OrderedDict()}
77 
78   @property
79   def python_packages(self):
80     return self._dependency[self._PYTHON_PACKAGE]
81 
82   def add_python_package(self, dependency, override=True):
83     """ add_single_python_package adds a dependency for the python package
84 
85     Args:
86       name: package name
87       version: it could be a specific version(1.10.0), or a range(>=1.0,<=2.0)
88         if not specified, the default is resolved automatically by the pip system.
89       override: whether to override the version if already existing in the dependency.
90     """
91     if dependency.name in self.python_packages and not override:
92       return
93     self.python_packages[dependency.name] = dependency
94 
95   def generate_pip_requirements(self, target_file):
96     """ write the python packages to a requirement file
97     the generated file follows the order of which the packages are added """
98     with open(target_file, 'w') as f:
99       for name, version in self.python_packages.items():
100         version = self.python_packages[name]
101         version_str = ''
102         if version.has_min_version():
103           version_str += ' >= ' + version.min_version + ','
104         if version.has_max_version():
105           version_str += ' <= ' + version.max_version + ','
106         f.write(name + version_str.rstrip(',') + '\n')
107 
108 def _dependency_to_requirements(dependency=[], filename='requirements.txt'):
109   """
110     Generates a requirement file based on the dependency
111     Args:
112       dependency (list): a list of VersionedDependency, which includes the package name and versions
113       filename (str): requirement file name, default as requirements.txt
114   """
115   dependency_helper = DependencyHelper()
116   for version in dependency:
117     dependency_helper.add_python_package(version)
118   dependency_helper.generate_pip_requirements(filename)
119 
120 def _generate_dockerfile(filename, base_image, python_version, requirement_filename=None, add_files=None):
121   """
122     generates dockerfiles
123     Args:
124       filename (str): target file name for the dockerfile.
125       base_image (str): the base image name.
126       python_version (str): choose python2 or python3
127       requirement_filename (str): requirement file name
128       add_files (Dict[str, str]): Map containing the files thats should be added to the container. add_files maps the build context relative source paths to the container destination paths.
129   """
130   if python_version not in ['python2', 'python3']:
131     raise ValueError('python_version has to be either python2 or python3')
132   with open(filename, 'w') as f:
133     f.write('FROM ' + base_image + '\n')
134     if python_version == 'python3':
135       f.write('RUN apt-get update -y && apt-get install --no-install-recommends -y -q python3 python3-pip python3-setuptools\n')
136     else:
137       f.write('RUN apt-get update -y && apt-get install --no-install-recommends -y -q python python-pip python-setuptools\n')
138     if requirement_filename is not None:
139       f.write('ADD ' + requirement_filename + ' /ml/requirements.txt\n')
140       if python_version == 'python3':
141         f.write('RUN pip3 install -r /ml/requirements.txt\n')
142       else:
143         f.write('RUN pip install -r /ml/requirements.txt\n')
144     
145     for src_path, dst_path in (add_files or {}).items():     
146       f.write('ADD ' + src_path + ' ' + dst_path + '\n')
147 
148 
149 def _configure_logger(logger):
150   """ _configure_logger configures the logger such that the info level logs
151   go to the stdout and the error(or above) level logs go to the stderr.
152   It is important for the Jupyter notebook log rendering """
153   if hasattr(_configure_logger, 'configured'):
154     # Skip the logger configuration the second time this function
155     # is called to avoid multiple streamhandlers bound to the logger.
156     return
157   setattr(_configure_logger, 'configured', 'true')
158   logger.setLevel(logging.INFO)
159   info_handler = logging.StreamHandler(stream=sys.stdout)
160   info_handler.addFilter(lambda record: record.levelno <= logging.INFO)
161   info_handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(message)s', datefmt='%Y-%m-%d %H:%M:%S'))
162   error_handler = logging.StreamHandler(sys.stderr)
163   error_handler.addFilter(lambda record: record.levelno > logging.INFO)
164   error_handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(message)s', datefmt='%Y-%m-%d %H:%M:%S'))
165   logger.addHandler(info_handler)
166   logger.addHandler(error_handler)
167 
168 
169 def build_python_component(component_func, target_image, base_image=None, dependency=[], staging_gcs_path=None, timeout=600, namespace='kubeflow', target_component_file=None, python_version='python3'):
170   """ build_component automatically builds a container image for the component_func
171   based on the base_image and pushes to the target_image.
172 
173   Args:
174     component_func (python function): The python function to build components upon
175     base_image (str): Docker image to use as a base image
176     target_image (str): Full URI to push the target image
177     staging_gcs_path (str): GCS blob that can store temporary build files
178     target_image (str): target image path
179     timeout (int): the timeout for the image build(in secs), default is 600 seconds
180     namespace (str): the namespace within which to run the kubernetes kaniko job, default is "kubeflow"
181     dependency (list): a list of VersionedDependency, which includes the package name and versions, default is empty
182     python_version (str): choose python2 or python3, default is python3
183   Raises:
184     ValueError: The function is not decorated with python_component decorator or the python_version is neither python2 nor python3
185   """
186 
187   _configure_logger(logging.getLogger())
188 
189   if component_func is None:
190     raise ValueError('component_func must not be None')
191   if target_image is None:
192     raise ValueError('target_image must not be None')
193 
194   if python_version not in ['python2', 'python3']:
195     raise ValueError('python_version has to be either python2 or python3')
196 
197   if staging_gcs_path is None:
198     raise ValueError('staging_gcs_path must not be None')
199 
200   if base_image is None:
201     base_image = getattr(component_func, '_component_base_image', None)
202   if base_image is None:
203     from ..components._python_op import get_default_base_image
204     base_image = get_default_base_image()
205     if isinstance(base_image, Callable):
206       base_image = base_image()
207 
208   logging.info('Build an image that is based on ' +
209                                   base_image +
210                                   ' and push the image to ' +
211                                   target_image)
212 
213   component_spec = _func_to_component_spec(component_func, base_image=base_image)
214   command_line_args = component_spec.implementation.container.command
215 
216   dash_c_index = command_line_args.index('-c')
217   program_code_index = dash_c_index + 1
218   program_code = command_line_args[program_code_index]
219   program_rel_path = 'ml/main.py'
220   program_container_path = '/' + program_rel_path
221 
222   # Replacing the inline code with calling a local program
223   # Before: python3 -u -c 'import sys ...' --param1 ...
224   # After:  python3 -u main.py --param1 ...
225   command_line_args[program_code_index] = program_container_path
226   command_line_args.pop(dash_c_index)
227 
228   if python_version == 'python2':
229     import warnings
230     warnings.warn('Python2 is not longer supported')
231     # Replacing the python interpreter
232     python_interpreter_index = command_line_args.index('python3')
233     command_line_args[python_interpreter_index] = python_version
234 
235   arc_docker_filename = 'Dockerfile'
236   arc_requirement_filename = 'requirements.txt'
237 
238   with tempfile.TemporaryDirectory() as local_build_dir:
239     # Write the program code to a file in the context directory
240     local_python_filepath = os.path.join(local_build_dir, program_rel_path)
241     os.makedirs(os.path.dirname(local_python_filepath), exist_ok=True)
242     with open(local_python_filepath, 'w') as f:
243       f.write(program_code)
244 
245     # Generate the python package requirements file in the context directory
246     local_requirement_filepath = os.path.join(local_build_dir, arc_requirement_filename)
247     _dependency_to_requirements(dependency, local_requirement_filepath)
248 
249     # Generate Dockerfile in the context directory
250     local_docker_filepath = os.path.join(local_build_dir, arc_docker_filename)
251     _generate_dockerfile(local_docker_filepath, base_image, python_version, arc_requirement_filename, add_files={program_rel_path: program_container_path})
252 
253     logging.info('Building and pushing container image.')
254     container_builder = ContainerBuilder(staging_gcs_path, target_image, namespace)
255     image_name_with_digest = container_builder.build(local_build_dir, arc_docker_filename, target_image, timeout)
256 
257   component_spec.implementation.container.image = image_name_with_digest
258 
259   # Optionally writing the component definition to a local file for sharing
260   target_component_file = target_component_file or getattr(component_func, '_component_target_component_file', None)
261   if target_component_file:
262     component_text = dump_yaml(component_spec.to_dict())
263     Path(target_component_file).write_text(component_text)
264 
265   task_factory_function = _create_task_factory_from_component_spec(component_spec)
266   return task_factory_function
267 
268 
269 def build_docker_image(staging_gcs_path, target_image, dockerfile_path, timeout=600, namespace='kubeflow'):
270   """ build_docker_image automatically builds a container image based on the specification in the dockerfile and
271   pushes to the target_image.
272 
273   Args:
274     staging_gcs_path (str): GCS blob that can store temporary build files
275     target_image (str): gcr path to push the final image
276     dockerfile_path (str): local path to the dockerfile
277     timeout (int): the timeout for the image build(in secs), default is 600 seconds
278     namespace (str): the namespace within which to run the kubernetes kaniko job, default is "kubeflow"
279   """
280   _configure_logger(logging.getLogger())
281 
282   with tempfile.TemporaryDirectory() as local_build_dir:
283     dockerfile_rel_path = 'Dockerfile'
284     dst_dockerfile_path = os.path.join(local_build_dir, dockerfile_rel_path)
285     shutil.copyfile(dockerfile_path, dst_dockerfile_path)
286 
287     container_builder = ContainerBuilder(staging_gcs_path, target_image, namespace=namespace)
288     image_name_with_digest = container_builder.build(local_build_dir, dockerfile_rel_path, target_image, timeout)
289 
290   logging.info('Build image complete.')
291   return image_name_with_digest
292
```
--- 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()

```

diff --git a/sdk/python/kfp/containers/_component_builder.py b/sdk/python/kfp/containers/_component_builder.py
--- a/sdk/python/kfp/containers/_component_builder.py
+++ b/sdk/python/kfp/containers/_component_builder.py
@@ -166,7 +166,7 @@
   logger.addHandler(error_handler)
 
 
-def build_python_component(component_func, target_image, base_image=None, dependency=[], staging_gcs_path=None, timeout=600, namespace='kubeflow', target_component_file=None, python_version='python3'):
+def build_python_component(component_func, target_image, base_image=None, dependency=[], staging_gcs_path=None, timeout=600, namespace=None, target_component_file=None, python_version='python3'):
   """ build_component automatically builds a container image for the component_func
   based on the base_image and pushes to the target_image.
 
@@ -177,7 +177,8 @@
     staging_gcs_path (str): GCS blob that can store temporary build files
     target_image (str): target image path
     timeout (int): the timeout for the image build(in secs), default is 600 seconds
-    namespace (str): the namespace within which to run the kubernetes kaniko job, default is "kubeflow"
+    namespace (str): the namespace within which to run the kubernetes kaniko job. If the
+    job is running on GKE and value is None the underlying functions will use the default namespace from GKE.  .
     dependency (list): a list of VersionedDependency, which includes the package name and versions, default is empty
     python_version (str): choose python2 or python3, default is python3
   Raises:
@@ -266,7 +267,7 @@
   return task_factory_function
 
 
-def build_docker_image(staging_gcs_path, target_image, dockerfile_path, timeout=600, namespace='kubeflow'):
+def build_docker_image(staging_gcs_path, target_image, dockerfile_path, timeout=600, namespace=None):
   """ build_docker_image automatically builds a container image based on the specification in the dockerfile and
   pushes to the target_image.
 
@@ -275,7 +276,8 @@
     target_image (str): gcr path to push the final image
     dockerfile_path (str): local path to the dockerfile
     timeout (int): the timeout for the image build(in secs), default is 600 seconds
-    namespace (str): the namespace within which to run the kubernetes kaniko job, default is "kubeflow"
+    namespace (str): the namespace within which to run the kubernetes kaniko job. Default is None. If the
+    job is running on GKE and value is None the underlying functions will use the default namespace from GKE.  
   """
   _configure_logger(logging.getLogger())

{"golden_diff": "diff --git a/sdk/python/kfp/containers/_component_builder.py b/sdk/python/kfp/containers/_component_builder.py\n--- a/sdk/python/kfp/containers/_component_builder.py\n+++ b/sdk/python/kfp/containers/_component_builder.py\n@@ -166,7 +166,7 @@\n   logger.addHandler(error_handler)\n \n \n-def build_python_component(component_func, target_image, base_image=None, dependency=[], staging_gcs_path=None, timeout=600, namespace='kubeflow', target_component_file=None, python_version='python3'):\n+def build_python_component(component_func, target_image, base_image=None, dependency=[], staging_gcs_path=None, timeout=600, namespace=None, target_component_file=None, python_version='python3'):\n   \"\"\" build_component automatically builds a container image for the component_func\n   based on the base_image and pushes to the target_image.\n \n@@ -177,7 +177,8 @@\n     staging_gcs_path (str): GCS blob that can store temporary build files\n     target_image (str): target image path\n     timeout (int): the timeout for the image build(in secs), default is 600 seconds\n-    namespace (str): the namespace within which to run the kubernetes kaniko job, default is \"kubeflow\"\n+    namespace (str): the namespace within which to run the kubernetes kaniko job. If the\n+    job is running on GKE and value is None the underlying functions will use the default namespace from GKE.  .\n     dependency (list): a list of VersionedDependency, which includes the package name and versions, default is empty\n     python_version (str): choose python2 or python3, default is python3\n   Raises:\n@@ -266,7 +267,7 @@\n   return task_factory_function\n \n \n-def build_docker_image(staging_gcs_path, target_image, dockerfile_path, timeout=600, namespace='kubeflow'):\n+def build_docker_image(staging_gcs_path, target_image, dockerfile_path, timeout=600, namespace=None):\n   \"\"\" build_docker_image automatically builds a container image based on the specification in the dockerfile and\n   pushes to the target_image.\n \n@@ -275,7 +276,8 @@\n     target_image (str): gcr path to push the final image\n     dockerfile_path (str): local path to the dockerfile\n     timeout (int): the timeout for the image build(in secs), default is 600 seconds\n-    namespace (str): the namespace within which to run the kubernetes kaniko job, default is \"kubeflow\"\n+    namespace (str): the namespace within which to run the kubernetes kaniko job. Default is None. If the\n+    job is running on GKE and value is None the underlying functions will use the default namespace from GKE.  \n   \"\"\"\n   _configure_logger(logging.getLogger())\n", "issue": "build_python_component does not work in KF 6.2 \ncompiler.build_python_component uses the default name space for pod creation. As of KF 6.2 the notebooks are running under a user name space( ex kubeflow-<username>) with editor service account. This service account does not have access to default kubeflow name space by design. \r\n\r\nSDK needs to be updated to use the user service account instead. \r\n\r\nsample error: \r\n\r\n`HTTP response body: {\"kind\":\"Status\",\"apiVersion\":\"v1\",\"metadata\":{},\"status\":\"Failure\",\"message\":\"pods is forbidden: User \\\"system:serviceaccount:kubeflow-chavoshi:default-editor\\\" cannot create resource \\\"pods\\\" in API group \\\"\\\" in the namespace \\\"kubeflow\\\"\",\"reason\":\"Forbidden\",\"details\":{\"kind\":\"pods\"},\"code\":403}\r\n`\r\nscreen shot: \r\nhttps://screenshot.googleplex.com/QotFfe0hgnW.png \n", "before_files": [{"content": "# Copyright 2018 Google LLC\n#\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 os\nimport inspect\nimport re\nimport sys\nimport tempfile\nimport logging\nimport shutil\nfrom collections import OrderedDict\nfrom pathlib import Path\nfrom typing import Callable\nfrom ..components._components import _create_task_factory_from_component_spec\nfrom ..components._python_op import _func_to_component_spec\nfrom ..components._yaml_utils import dump_yaml\nfrom ._container_builder import ContainerBuilder\n\nclass VersionedDependency(object):\n  \"\"\" DependencyVersion specifies the versions \"\"\"\n  def __init__(self, name, version=None, min_version=None, max_version=None):\n    \"\"\" if version is specified, no need for min_version or max_version;\n     if both are specified, version is adopted \"\"\"\n    self._name = name\n    if version is not None:\n      self._min_version = version\n      self._max_version = version\n    else:\n      self._min_version = min_version\n      self._max_version = max_version\n\n  @property\n  def name(self):\n    return self._name\n\n  @property\n  def min_version(self):\n    return self._min_version\n\n  @min_version.setter\n  def min_version(self, min_version):\n    self._min_version = min_version\n\n  def has_min_version(self):\n    return self._min_version != None\n\n  @property\n  def max_version(self):\n    return self._max_version\n\n  @max_version.setter\n  def max_version(self, max_version):\n    self._max_version = max_version\n\n  def has_max_version(self):\n    return self._max_version != None\n\n  def has_versions(self):\n    return (self.has_min_version()) or (self.has_max_version())\n\nclass DependencyHelper(object):\n  \"\"\" DependencyHelper manages software dependency information \"\"\"\n  def __init__(self):\n    self._PYTHON_PACKAGE = 'PYTHON_PACKAGE'\n    self._dependency = {self._PYTHON_PACKAGE:OrderedDict()}\n\n  @property\n  def python_packages(self):\n    return self._dependency[self._PYTHON_PACKAGE]\n\n  def add_python_package(self, dependency, override=True):\n    \"\"\" add_single_python_package adds a dependency for the python package\n\n    Args:\n      name: package name\n      version: it could be a specific version(1.10.0), or a range(>=1.0,<=2.0)\n        if not specified, the default is resolved automatically by the pip system.\n      override: whether to override the version if already existing in the dependency.\n    \"\"\"\n    if dependency.name in self.python_packages and not override:\n      return\n    self.python_packages[dependency.name] = dependency\n\n  def generate_pip_requirements(self, target_file):\n    \"\"\" write the python packages to a requirement file\n    the generated file follows the order of which the packages are added \"\"\"\n    with open(target_file, 'w') as f:\n      for name, version in self.python_packages.items():\n        version = self.python_packages[name]\n        version_str = ''\n        if version.has_min_version():\n          version_str += ' >= ' + version.min_version + ','\n        if version.has_max_version():\n          version_str += ' <= ' + version.max_version + ','\n        f.write(name + version_str.rstrip(',') + '\\n')\n\ndef _dependency_to_requirements(dependency=[], filename='requirements.txt'):\n  \"\"\"\n    Generates a requirement file based on the dependency\n    Args:\n      dependency (list): a list of VersionedDependency, which includes the package name and versions\n      filename (str): requirement file name, default as requirements.txt\n  \"\"\"\n  dependency_helper = DependencyHelper()\n  for version in dependency:\n    dependency_helper.add_python_package(version)\n  dependency_helper.generate_pip_requirements(filename)\n\ndef _generate_dockerfile(filename, base_image, python_version, requirement_filename=None, add_files=None):\n  \"\"\"\n    generates dockerfiles\n    Args:\n      filename (str): target file name for the dockerfile.\n      base_image (str): the base image name.\n      python_version (str): choose python2 or python3\n      requirement_filename (str): requirement file name\n      add_files (Dict[str, str]): Map containing the files thats should be added to the container. add_files maps the build context relative source paths to the container destination paths.\n  \"\"\"\n  if python_version not in ['python2', 'python3']:\n    raise ValueError('python_version has to be either python2 or python3')\n  with open(filename, 'w') as f:\n    f.write('FROM ' + base_image + '\\n')\n    if python_version == 'python3':\n      f.write('RUN apt-get update -y && apt-get install --no-install-recommends -y -q python3 python3-pip python3-setuptools\\n')\n    else:\n      f.write('RUN apt-get update -y && apt-get install --no-install-recommends -y -q python python-pip python-setuptools\\n')\n    if requirement_filename is not None:\n      f.write('ADD ' + requirement_filename + ' /ml/requirements.txt\\n')\n      if python_version == 'python3':\n        f.write('RUN pip3 install -r /ml/requirements.txt\\n')\n      else:\n        f.write('RUN pip install -r /ml/requirements.txt\\n')\n    \n    for src_path, dst_path in (add_files or {}).items():     \n      f.write('ADD ' + src_path + ' ' + dst_path + '\\n')\n\n\ndef _configure_logger(logger):\n  \"\"\" _configure_logger configures the logger such that the info level logs\n  go to the stdout and the error(or above) level logs go to the stderr.\n  It is important for the Jupyter notebook log rendering \"\"\"\n  if hasattr(_configure_logger, 'configured'):\n    # Skip the logger configuration the second time this function\n    # is called to avoid multiple streamhandlers bound to the logger.\n    return\n  setattr(_configure_logger, 'configured', 'true')\n  logger.setLevel(logging.INFO)\n  info_handler = logging.StreamHandler(stream=sys.stdout)\n  info_handler.addFilter(lambda record: record.levelno <= logging.INFO)\n  info_handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(message)s', datefmt='%Y-%m-%d %H:%M:%S'))\n  error_handler = logging.StreamHandler(sys.stderr)\n  error_handler.addFilter(lambda record: record.levelno > logging.INFO)\n  error_handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(message)s', datefmt='%Y-%m-%d %H:%M:%S'))\n  logger.addHandler(info_handler)\n  logger.addHandler(error_handler)\n\n\ndef build_python_component(component_func, target_image, base_image=None, dependency=[], staging_gcs_path=None, timeout=600, namespace='kubeflow', target_component_file=None, python_version='python3'):\n  \"\"\" build_component automatically builds a container image for the component_func\n  based on the base_image and pushes to the target_image.\n\n  Args:\n    component_func (python function): The python function to build components upon\n    base_image (str): Docker image to use as a base image\n    target_image (str): Full URI to push the target image\n    staging_gcs_path (str): GCS blob that can store temporary build files\n    target_image (str): target image path\n    timeout (int): the timeout for the image build(in secs), default is 600 seconds\n    namespace (str): the namespace within which to run the kubernetes kaniko job, default is \"kubeflow\"\n    dependency (list): a list of VersionedDependency, which includes the package name and versions, default is empty\n    python_version (str): choose python2 or python3, default is python3\n  Raises:\n    ValueError: The function is not decorated with python_component decorator or the python_version is neither python2 nor python3\n  \"\"\"\n\n  _configure_logger(logging.getLogger())\n\n  if component_func is None:\n    raise ValueError('component_func must not be None')\n  if target_image is None:\n    raise ValueError('target_image must not be None')\n\n  if python_version not in ['python2', 'python3']:\n    raise ValueError('python_version has to be either python2 or python3')\n\n  if staging_gcs_path is None:\n    raise ValueError('staging_gcs_path must not be None')\n\n  if base_image is None:\n    base_image = getattr(component_func, '_component_base_image', None)\n  if base_image is None:\n    from ..components._python_op import get_default_base_image\n    base_image = get_default_base_image()\n    if isinstance(base_image, Callable):\n      base_image = base_image()\n\n  logging.info('Build an image that is based on ' +\n                                  base_image +\n                                  ' and push the image to ' +\n                                  target_image)\n\n  component_spec = _func_to_component_spec(component_func, base_image=base_image)\n  command_line_args = component_spec.implementation.container.command\n\n  dash_c_index = command_line_args.index('-c')\n  program_code_index = dash_c_index + 1\n  program_code = command_line_args[program_code_index]\n  program_rel_path = 'ml/main.py'\n  program_container_path = '/' + program_rel_path\n\n  # Replacing the inline code with calling a local program\n  # Before: python3 -u -c 'import sys ...' --param1 ...\n  # After:  python3 -u main.py --param1 ...\n  command_line_args[program_code_index] = program_container_path\n  command_line_args.pop(dash_c_index)\n\n  if python_version == 'python2':\n    import warnings\n    warnings.warn('Python2 is not longer supported')\n    # Replacing the python interpreter\n    python_interpreter_index = command_line_args.index('python3')\n    command_line_args[python_interpreter_index] = python_version\n\n  arc_docker_filename = 'Dockerfile'\n  arc_requirement_filename = 'requirements.txt'\n\n  with tempfile.TemporaryDirectory() as local_build_dir:\n    # Write the program code to a file in the context directory\n    local_python_filepath = os.path.join(local_build_dir, program_rel_path)\n    os.makedirs(os.path.dirname(local_python_filepath), exist_ok=True)\n    with open(local_python_filepath, 'w') as f:\n      f.write(program_code)\n\n    # Generate the python package requirements file in the context directory\n    local_requirement_filepath = os.path.join(local_build_dir, arc_requirement_filename)\n    _dependency_to_requirements(dependency, local_requirement_filepath)\n\n    # Generate Dockerfile in the context directory\n    local_docker_filepath = os.path.join(local_build_dir, arc_docker_filename)\n    _generate_dockerfile(local_docker_filepath, base_image, python_version, arc_requirement_filename, add_files={program_rel_path: program_container_path})\n\n    logging.info('Building and pushing container image.')\n    container_builder = ContainerBuilder(staging_gcs_path, target_image, namespace)\n    image_name_with_digest = container_builder.build(local_build_dir, arc_docker_filename, target_image, timeout)\n\n  component_spec.implementation.container.image = image_name_with_digest\n\n  # Optionally writing the component definition to a local file for sharing\n  target_component_file = target_component_file or getattr(component_func, '_component_target_component_file', None)\n  if target_component_file:\n    component_text = dump_yaml(component_spec.to_dict())\n    Path(target_component_file).write_text(component_text)\n\n  task_factory_function = _create_task_factory_from_component_spec(component_spec)\n  return task_factory_function\n\n\ndef build_docker_image(staging_gcs_path, target_image, dockerfile_path, timeout=600, namespace='kubeflow'):\n  \"\"\" build_docker_image automatically builds a container image based on the specification in the dockerfile and\n  pushes to the target_image.\n\n  Args:\n    staging_gcs_path (str): GCS blob that can store temporary build files\n    target_image (str): gcr path to push the final image\n    dockerfile_path (str): local path to the dockerfile\n    timeout (int): the timeout for the image build(in secs), default is 600 seconds\n    namespace (str): the namespace within which to run the kubernetes kaniko job, default is \"kubeflow\"\n  \"\"\"\n  _configure_logger(logging.getLogger())\n\n  with tempfile.TemporaryDirectory() as local_build_dir:\n    dockerfile_rel_path = 'Dockerfile'\n    dst_dockerfile_path = os.path.join(local_build_dir, dockerfile_rel_path)\n    shutil.copyfile(dockerfile_path, dst_dockerfile_path)\n\n    container_builder = ContainerBuilder(staging_gcs_path, target_image, namespace=namespace)\n    image_name_with_digest = container_builder.build(local_build_dir, dockerfile_rel_path, target_image, timeout)\n\n  logging.info('Build image complete.')\n  return image_name_with_digest\n", "path": "sdk/python/kfp/containers/_component_builder.py"}], "after_files": [{"content": "# Copyright 2018 Google LLC\n#\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 os\nimport inspect\nimport re\nimport sys\nimport tempfile\nimport logging\nimport shutil\nfrom collections import OrderedDict\nfrom pathlib import Path\nfrom typing import Callable\nfrom ..components._components import _create_task_factory_from_component_spec\nfrom ..components._python_op import _func_to_component_spec\nfrom ..components._yaml_utils import dump_yaml\nfrom ._container_builder import ContainerBuilder\n\nclass VersionedDependency(object):\n  \"\"\" DependencyVersion specifies the versions \"\"\"\n  def __init__(self, name, version=None, min_version=None, max_version=None):\n    \"\"\" if version is specified, no need for min_version or max_version;\n     if both are specified, version is adopted \"\"\"\n    self._name = name\n    if version is not None:\n      self._min_version = version\n      self._max_version = version\n    else:\n      self._min_version = min_version\n      self._max_version = max_version\n\n  @property\n  def name(self):\n    return self._name\n\n  @property\n  def min_version(self):\n    return self._min_version\n\n  @min_version.setter\n  def min_version(self, min_version):\n    self._min_version = min_version\n\n  def has_min_version(self):\n    return self._min_version != None\n\n  @property\n  def max_version(self):\n    return self._max_version\n\n  @max_version.setter\n  def max_version(self, max_version):\n    self._max_version = max_version\n\n  def has_max_version(self):\n    return self._max_version != None\n\n  def has_versions(self):\n    return (self.has_min_version()) or (self.has_max_version())\n\nclass DependencyHelper(object):\n  \"\"\" DependencyHelper manages software dependency information \"\"\"\n  def __init__(self):\n    self._PYTHON_PACKAGE = 'PYTHON_PACKAGE'\n    self._dependency = {self._PYTHON_PACKAGE:OrderedDict()}\n\n  @property\n  def python_packages(self):\n    return self._dependency[self._PYTHON_PACKAGE]\n\n  def add_python_package(self, dependency, override=True):\n    \"\"\" add_single_python_package adds a dependency for the python package\n\n    Args:\n      name: package name\n      version: it could be a specific version(1.10.0), or a range(>=1.0,<=2.0)\n        if not specified, the default is resolved automatically by the pip system.\n      override: whether to override the version if already existing in the dependency.\n    \"\"\"\n    if dependency.name in self.python_packages and not override:\n      return\n    self.python_packages[dependency.name] = dependency\n\n  def generate_pip_requirements(self, target_file):\n    \"\"\" write the python packages to a requirement file\n    the generated file follows the order of which the packages are added \"\"\"\n    with open(target_file, 'w') as f:\n      for name, version in self.python_packages.items():\n        version = self.python_packages[name]\n        version_str = ''\n        if version.has_min_version():\n          version_str += ' >= ' + version.min_version + ','\n        if version.has_max_version():\n          version_str += ' <= ' + version.max_version + ','\n        f.write(name + version_str.rstrip(',') + '\\n')\n\ndef _dependency_to_requirements(dependency=[], filename='requirements.txt'):\n  \"\"\"\n    Generates a requirement file based on the dependency\n    Args:\n      dependency (list): a list of VersionedDependency, which includes the package name and versions\n      filename (str): requirement file name, default as requirements.txt\n  \"\"\"\n  dependency_helper = DependencyHelper()\n  for version in dependency:\n    dependency_helper.add_python_package(version)\n  dependency_helper.generate_pip_requirements(filename)\n\ndef _generate_dockerfile(filename, base_image, python_version, requirement_filename=None, add_files=None):\n  \"\"\"\n    generates dockerfiles\n    Args:\n      filename (str): target file name for the dockerfile.\n      base_image (str): the base image name.\n      python_version (str): choose python2 or python3\n      requirement_filename (str): requirement file name\n      add_files (Dict[str, str]): Map containing the files thats should be added to the container. add_files maps the build context relative source paths to the container destination paths.\n  \"\"\"\n  if python_version not in ['python2', 'python3']:\n    raise ValueError('python_version has to be either python2 or python3')\n  with open(filename, 'w') as f:\n    f.write('FROM ' + base_image + '\\n')\n    if python_version == 'python3':\n      f.write('RUN apt-get update -y && apt-get install --no-install-recommends -y -q python3 python3-pip python3-setuptools\\n')\n    else:\n      f.write('RUN apt-get update -y && apt-get install --no-install-recommends -y -q python python-pip python-setuptools\\n')\n    if requirement_filename is not None:\n      f.write('ADD ' + requirement_filename + ' /ml/requirements.txt\\n')\n      if python_version == 'python3':\n        f.write('RUN pip3 install -r /ml/requirements.txt\\n')\n      else:\n        f.write('RUN pip install -r /ml/requirements.txt\\n')\n    \n    for src_path, dst_path in (add_files or {}).items():     \n      f.write('ADD ' + src_path + ' ' + dst_path + '\\n')\n\n\ndef _configure_logger(logger):\n  \"\"\" _configure_logger configures the logger such that the info level logs\n  go to the stdout and the error(or above) level logs go to the stderr.\n  It is important for the Jupyter notebook log rendering \"\"\"\n  if hasattr(_configure_logger, 'configured'):\n    # Skip the logger configuration the second time this function\n    # is called to avoid multiple streamhandlers bound to the logger.\n    return\n  setattr(_configure_logger, 'configured', 'true')\n  logger.setLevel(logging.INFO)\n  info_handler = logging.StreamHandler(stream=sys.stdout)\n  info_handler.addFilter(lambda record: record.levelno <= logging.INFO)\n  info_handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(message)s', datefmt='%Y-%m-%d %H:%M:%S'))\n  error_handler = logging.StreamHandler(sys.stderr)\n  error_handler.addFilter(lambda record: record.levelno > logging.INFO)\n  error_handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(message)s', datefmt='%Y-%m-%d %H:%M:%S'))\n  logger.addHandler(info_handler)\n  logger.addHandler(error_handler)\n\n\ndef build_python_component(component_func, target_image, base_image=None, dependency=[], staging_gcs_path=None, timeout=600, namespace=None, target_component_file=None, python_version='python3'):\n  \"\"\" build_component automatically builds a container image for the component_func\n  based on the base_image and pushes to the target_image.\n\n  Args:\n    component_func (python function): The python function to build components upon\n    base_image (str): Docker image to use as a base image\n    target_image (str): Full URI to push the target image\n    staging_gcs_path (str): GCS blob that can store temporary build files\n    target_image (str): target image path\n    timeout (int): the timeout for the image build(in secs), default is 600 seconds\n    namespace (str): the namespace within which to run the kubernetes kaniko job. If the\n    job is running on GKE and value is None the underlying functions will use the default namespace from GKE.  .\n    dependency (list): a list of VersionedDependency, which includes the package name and versions, default is empty\n    python_version (str): choose python2 or python3, default is python3\n  Raises:\n    ValueError: The function is not decorated with python_component decorator or the python_version is neither python2 nor python3\n  \"\"\"\n\n  _configure_logger(logging.getLogger())\n\n  if component_func is None:\n    raise ValueError('component_func must not be None')\n  if target_image is None:\n    raise ValueError('target_image must not be None')\n\n  if python_version not in ['python2', 'python3']:\n    raise ValueError('python_version has to be either python2 or python3')\n\n  if staging_gcs_path is None:\n    raise ValueError('staging_gcs_path must not be None')\n\n  if base_image is None:\n    base_image = getattr(component_func, '_component_base_image', None)\n  if base_image is None:\n    from ..components._python_op import get_default_base_image\n    base_image = get_default_base_image()\n    if isinstance(base_image, Callable):\n      base_image = base_image()\n\n  logging.info('Build an image that is based on ' +\n                                  base_image +\n                                  ' and push the image to ' +\n                                  target_image)\n\n  component_spec = _func_to_component_spec(component_func, base_image=base_image)\n  command_line_args = component_spec.implementation.container.command\n\n  dash_c_index = command_line_args.index('-c')\n  program_code_index = dash_c_index + 1\n  program_code = command_line_args[program_code_index]\n  program_rel_path = 'ml/main.py'\n  program_container_path = '/' + program_rel_path\n\n  # Replacing the inline code with calling a local program\n  # Before: python3 -u -c 'import sys ...' --param1 ...\n  # After:  python3 -u main.py --param1 ...\n  command_line_args[program_code_index] = program_container_path\n  command_line_args.pop(dash_c_index)\n\n  if python_version == 'python2':\n    import warnings\n    warnings.warn('Python2 is not longer supported')\n    # Replacing the python interpreter\n    python_interpreter_index = command_line_args.index('python3')\n    command_line_args[python_interpreter_index] = python_version\n\n  arc_docker_filename = 'Dockerfile'\n  arc_requirement_filename = 'requirements.txt'\n\n  with tempfile.TemporaryDirectory() as local_build_dir:\n    # Write the program code to a file in the context directory\n    local_python_filepath = os.path.join(local_build_dir, program_rel_path)\n    os.makedirs(os.path.dirname(local_python_filepath), exist_ok=True)\n    with open(local_python_filepath, 'w') as f:\n      f.write(program_code)\n\n    # Generate the python package requirements file in the context directory\n    local_requirement_filepath = os.path.join(local_build_dir, arc_requirement_filename)\n    _dependency_to_requirements(dependency, local_requirement_filepath)\n\n    # Generate Dockerfile in the context directory\n    local_docker_filepath = os.path.join(local_build_dir, arc_docker_filename)\n    _generate_dockerfile(local_docker_filepath, base_image, python_version, arc_requirement_filename, add_files={program_rel_path: program_container_path})\n\n    logging.info('Building and pushing container image.')\n    container_builder = ContainerBuilder(staging_gcs_path, target_image, namespace)\n    image_name_with_digest = container_builder.build(local_build_dir, arc_docker_filename, target_image, timeout)\n\n  component_spec.implementation.container.image = image_name_with_digest\n\n  # Optionally writing the component definition to a local file for sharing\n  target_component_file = target_component_file or getattr(component_func, '_component_target_component_file', None)\n  if target_component_file:\n    component_text = dump_yaml(component_spec.to_dict())\n    Path(target_component_file).write_text(component_text)\n\n  task_factory_function = _create_task_factory_from_component_spec(component_spec)\n  return task_factory_function\n\n\ndef build_docker_image(staging_gcs_path, target_image, dockerfile_path, timeout=600, namespace=None):\n  \"\"\" build_docker_image automatically builds a container image based on the specification in the dockerfile and\n  pushes to the target_image.\n\n  Args:\n    staging_gcs_path (str): GCS blob that can store temporary build files\n    target_image (str): gcr path to push the final image\n    dockerfile_path (str): local path to the dockerfile\n    timeout (int): the timeout for the image build(in secs), default is 600 seconds\n    namespace (str): the namespace within which to run the kubernetes kaniko job. Default is None. If the\n    job is running on GKE and value is None the underlying functions will use the default namespace from GKE.  \n  \"\"\"\n  _configure_logger(logging.getLogger())\n\n  with tempfile.TemporaryDirectory() as local_build_dir:\n    dockerfile_rel_path = 'Dockerfile'\n    dst_dockerfile_path = os.path.join(local_build_dir, dockerfile_rel_path)\n    shutil.copyfile(dockerfile_path, dst_dockerfile_path)\n\n    container_builder = ContainerBuilder(staging_gcs_path, target_image, namespace=namespace)\n    image_name_with_digest = container_builder.build(local_build_dir, dockerfile_rel_path, target_image, timeout)\n\n  logging.info('Build image complete.')\n  return image_name_with_digest\n", "path": "sdk/python/kfp/containers/_component_builder.py"}]}