We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
allow output artifact store configuration (vs hard coded)
it seems like the output artifacts are always stored in a specific minio service, port, namespace, bucket, secrets, etc (`minio-service.kubeflow:9000`). 

see: https://github.com/kubeflow/pipelines/blob/f40a22a3f4a8e06d20cf3e3f425b5058d5c87e0b/sdk/python/kfp/compiler/_op_to_template.py#L148

it would be great to make it flexible, e.g. allow using S3, or change namespace or bucket names.
i suggest making it configurable, i can do such PR if we agree its needed. 
flexible pipeline service (host) path in client SDK 
when creating an SDK `Client()` the path to `ml-pipeline` API service is loaded from a hard coded value (`ml-pipeline.kubeflow.svc.cluster.local:8888`) which indicate a specific k8s namespace. it can be valuable to load that default value from an env variable, i.e. changing the line in `_client.py` from:

`config.host = host if host else Client.IN_CLUSTER_DNS_NAME`

to:

`config.host = host or os.environ.get('ML_PIPELINE_DNS_NAME',Client.IN_CLUSTER_DNS_NAME)`

also note that when a user provide the `host` parameter, the ipython output points to the API server and not to the UI service (see the logic in `_get_url_prefix()`), it seems like a potential bug

if its acceptable i can submit a PR for the line change above
 

--- 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/gcp.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 from kubernetes.client import V1Toleration, V1Affinity, V1NodeAffinity, \
16   V1NodeSelector, V1NodeSelectorTerm, V1NodeSelectorRequirement, V1PreferredSchedulingTerm
17 
18 def use_gcp_secret(secret_name='user-gcp-sa', secret_file_path_in_volume=None, volume_name=None, secret_volume_mount_path='/secret/gcp-credentials'):
19     """An operator that configures the container to use GCP service account by service account key
20         stored in a Kubernetes secret.
21 
22         For cluster setup and alternatives to using service account key, check https://www.kubeflow.org/docs/gke/authentication-pipelines/.
23     """
24 
25     # permitted values for secret_name = ['admin-gcp-sa', 'user-gcp-sa']
26     if secret_file_path_in_volume is None:
27         secret_file_path_in_volume = '/' + secret_name + '.json'
28 
29     if volume_name is None:
30         volume_name = 'gcp-credentials-' + secret_name
31 
32     else:
33         import warnings
34         warnings.warn('The volume_name parameter is deprecated and will be removed in next release. The volume names are now generated automatically.', DeprecationWarning)
35     
36     def _use_gcp_secret(task):
37         from kubernetes import client as k8s_client
38         task = task.add_volume(
39             k8s_client.V1Volume(
40                 name=volume_name,
41                 secret=k8s_client.V1SecretVolumeSource(
42                     secret_name=secret_name,
43                 )
44             )
45         )
46         task.container \
47             .add_volume_mount(
48                     k8s_client.V1VolumeMount(
49                         name=volume_name,
50                         mount_path=secret_volume_mount_path,
51                     )
52                 ) \
53             .add_env_variable(
54                 k8s_client.V1EnvVar(
55                     name='GOOGLE_APPLICATION_CREDENTIALS',
56                     value=secret_volume_mount_path + secret_file_path_in_volume,
57                 )
58             ) \
59             .add_env_variable(
60                 k8s_client.V1EnvVar(
61                     name='CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE',
62                     value=secret_volume_mount_path + secret_file_path_in_volume,
63                 )
64             ) # Set GCloud Credentials by using the env var override.
65               # TODO: Is there a better way for GCloud to pick up the credential?
66         return task
67     
68     return _use_gcp_secret
69 
70 def use_tpu(tpu_cores: int, tpu_resource: str, tf_version: str):
71     """An operator that configures GCP TPU spec in a container op.
72 
73     Args:
74       tpu_cores: Required. The number of cores of TPU resource. 
75         For example, the value can be '8', '32', '128', etc.
76         Check more details at: https://cloud.google.com/tpu/docs/kubernetes-engine-setup#pod-spec.
77       tpu_resource: Required. The resource name of the TPU resource. 
78         For example, the value can be 'v2', 'preemptible-v1', 'v3' or 'preemptible-v3'.
79         Check more details at: https://cloud.google.com/tpu/docs/kubernetes-engine-setup#pod-spec.
80       tf_version: Required. The TensorFlow version that the TPU nodes use.
81         For example, the value can be '1.12', '1.11', '1.9' or '1.8'.
82         Check more details at: https://cloud.google.com/tpu/docs/supported-versions.
83     """
84 
85     def _set_tpu_spec(task):
86         task.add_pod_annotation('tf-version.cloud-tpus.google.com', tf_version)
87         task.add_resource_limit('cloud-tpus.google.com/{}'.format(tpu_resource), str(tpu_cores))
88         return task
89 
90     return _set_tpu_spec
91 
92 def use_preemptible_nodepool(toleration: V1Toleration = V1Toleration(effect='NoSchedule',
93                                                              key='preemptible',
94                                                              operator='Equal',
95                                                              value='true'),
96                               hard_constraint: bool = False):
97   """An operator that configures the GKE preemptible in a container op.
98   Args:
99     toleration (V1Toleration): toleration to pods, default is the preemptible label.
100     hard_constraint (bool): the constraint of scheduling the pods on preemptible
101         nodepools is hard. (Default: False)
102   """
103 
104   def _set_preemptible(task):
105     task.add_toleration(toleration)
106     node_selector_term = V1NodeSelectorTerm(match_expressions=[
107         V1NodeSelectorRequirement(key='cloud.google.com/gke-preemptible',
108                                   operator='In',
109                                   values=['true'])]
110     )
111     if hard_constraint:
112       node_affinity = V1NodeAffinity(required_during_scheduling_ignored_during_execution=
113                         V1NodeSelector(node_selector_terms=[node_selector_term]))
114     else:
115       node_affinity = V1NodeAffinity(preferred_during_scheduling_ignored_during_execution=[
116                         V1PreferredSchedulingTerm(preference=node_selector_term,
117                                                   weight=50)
118       ])
119     affinity = V1Affinity(node_affinity=node_affinity)
120     task.add_affinity(affinity=affinity)
121     return task
122 
123   return _set_preemptible
124 
125 def add_gpu_toleration(toleration: V1Toleration = V1Toleration(
126     effect='NoSchedule', key='nvidia.com/gpu', operator='Equal', value='true')):
127     """An operator that configures the GKE GPU nodes in a container op.
128 
129     Args:
130       toleration {V1Toleration} -- toleration to pods, default is the nvidia.com/gpu label.
131     """
132 
133     def _set_toleration(task):
134         task.add_toleration(toleration)
135 
136     return _set_toleration
137
```
--- 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/gcp.py b/sdk/python/kfp/gcp.py
--- a/sdk/python/kfp/gcp.py
+++ b/sdk/python/kfp/gcp.py
@@ -84,7 +84,7 @@
 
     def _set_tpu_spec(task):
         task.add_pod_annotation('tf-version.cloud-tpus.google.com', tf_version)
-        task.add_resource_limit('cloud-tpus.google.com/{}'.format(tpu_resource), str(tpu_cores))
+        task.container.add_resource_limit('cloud-tpus.google.com/{}'.format(tpu_resource), str(tpu_cores))
         return task
 
     return _set_tpu_spec

{"golden_diff": "diff --git a/sdk/python/kfp/gcp.py b/sdk/python/kfp/gcp.py\n--- a/sdk/python/kfp/gcp.py\n+++ b/sdk/python/kfp/gcp.py\n@@ -84,7 +84,7 @@\n \n     def _set_tpu_spec(task):\n         task.add_pod_annotation('tf-version.cloud-tpus.google.com', tf_version)\n-        task.add_resource_limit('cloud-tpus.google.com/{}'.format(tpu_resource), str(tpu_cores))\n+        task.container.add_resource_limit('cloud-tpus.google.com/{}'.format(tpu_resource), str(tpu_cores))\n         return task\n \n     return _set_tpu_spec\n", "issue": "allow output artifact store configuration (vs hard coded)\nit seems like the output artifacts are always stored in a specific minio service, port, namespace, bucket, secrets, etc (`minio-service.kubeflow:9000`). \r\n\r\nsee: https://github.com/kubeflow/pipelines/blob/f40a22a3f4a8e06d20cf3e3f425b5058d5c87e0b/sdk/python/kfp/compiler/_op_to_template.py#L148\r\n\r\nit would be great to make it flexible, e.g. allow using S3, or change namespace or bucket names.\r\ni suggest making it configurable, i can do such PR if we agree its needed. \nflexible pipeline service (host) path in client SDK \nwhen creating an SDK `Client()` the path to `ml-pipeline` API service is loaded from a hard coded value (`ml-pipeline.kubeflow.svc.cluster.local:8888`) which indicate a specific k8s namespace. it can be valuable to load that default value from an env variable, i.e. changing the line in `_client.py` from:\r\n\r\n`config.host = host if host else Client.IN_CLUSTER_DNS_NAME`\r\n\r\nto:\r\n\r\n`config.host = host or os.environ.get('ML_PIPELINE_DNS_NAME',Client.IN_CLUSTER_DNS_NAME)`\r\n\r\nalso note that when a user provide the `host` parameter, the ipython output points to the API server and not to the UI service (see the logic in `_get_url_prefix()`), it seems like a potential bug\r\n\r\nif its acceptable i can submit a PR for the line change above\r\n \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\nfrom kubernetes.client import V1Toleration, V1Affinity, V1NodeAffinity, \\\n  V1NodeSelector, V1NodeSelectorTerm, V1NodeSelectorRequirement, V1PreferredSchedulingTerm\n\ndef use_gcp_secret(secret_name='user-gcp-sa', secret_file_path_in_volume=None, volume_name=None, secret_volume_mount_path='/secret/gcp-credentials'):\n    \"\"\"An operator that configures the container to use GCP service account by service account key\n        stored in a Kubernetes secret.\n\n        For cluster setup and alternatives to using service account key, check https://www.kubeflow.org/docs/gke/authentication-pipelines/.\n    \"\"\"\n\n    # permitted values for secret_name = ['admin-gcp-sa', 'user-gcp-sa']\n    if secret_file_path_in_volume is None:\n        secret_file_path_in_volume = '/' + secret_name + '.json'\n\n    if volume_name is None:\n        volume_name = 'gcp-credentials-' + secret_name\n\n    else:\n        import warnings\n        warnings.warn('The volume_name parameter is deprecated and will be removed in next release. The volume names are now generated automatically.', DeprecationWarning)\n    \n    def _use_gcp_secret(task):\n        from kubernetes import client as k8s_client\n        task = task.add_volume(\n            k8s_client.V1Volume(\n                name=volume_name,\n                secret=k8s_client.V1SecretVolumeSource(\n                    secret_name=secret_name,\n                )\n            )\n        )\n        task.container \\\n            .add_volume_mount(\n                    k8s_client.V1VolumeMount(\n                        name=volume_name,\n                        mount_path=secret_volume_mount_path,\n                    )\n                ) \\\n            .add_env_variable(\n                k8s_client.V1EnvVar(\n                    name='GOOGLE_APPLICATION_CREDENTIALS',\n                    value=secret_volume_mount_path + secret_file_path_in_volume,\n                )\n            ) \\\n            .add_env_variable(\n                k8s_client.V1EnvVar(\n                    name='CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE',\n                    value=secret_volume_mount_path + secret_file_path_in_volume,\n                )\n            ) # Set GCloud Credentials by using the env var override.\n              # TODO: Is there a better way for GCloud to pick up the credential?\n        return task\n    \n    return _use_gcp_secret\n\ndef use_tpu(tpu_cores: int, tpu_resource: str, tf_version: str):\n    \"\"\"An operator that configures GCP TPU spec in a container op.\n\n    Args:\n      tpu_cores: Required. The number of cores of TPU resource. \n        For example, the value can be '8', '32', '128', etc.\n        Check more details at: https://cloud.google.com/tpu/docs/kubernetes-engine-setup#pod-spec.\n      tpu_resource: Required. The resource name of the TPU resource. \n        For example, the value can be 'v2', 'preemptible-v1', 'v3' or 'preemptible-v3'.\n        Check more details at: https://cloud.google.com/tpu/docs/kubernetes-engine-setup#pod-spec.\n      tf_version: Required. The TensorFlow version that the TPU nodes use.\n        For example, the value can be '1.12', '1.11', '1.9' or '1.8'.\n        Check more details at: https://cloud.google.com/tpu/docs/supported-versions.\n    \"\"\"\n\n    def _set_tpu_spec(task):\n        task.add_pod_annotation('tf-version.cloud-tpus.google.com', tf_version)\n        task.add_resource_limit('cloud-tpus.google.com/{}'.format(tpu_resource), str(tpu_cores))\n        return task\n\n    return _set_tpu_spec\n\ndef use_preemptible_nodepool(toleration: V1Toleration = V1Toleration(effect='NoSchedule',\n                                                             key='preemptible',\n                                                             operator='Equal',\n                                                             value='true'),\n                              hard_constraint: bool = False):\n  \"\"\"An operator that configures the GKE preemptible in a container op.\n  Args:\n    toleration (V1Toleration): toleration to pods, default is the preemptible label.\n    hard_constraint (bool): the constraint of scheduling the pods on preemptible\n        nodepools is hard. (Default: False)\n  \"\"\"\n\n  def _set_preemptible(task):\n    task.add_toleration(toleration)\n    node_selector_term = V1NodeSelectorTerm(match_expressions=[\n        V1NodeSelectorRequirement(key='cloud.google.com/gke-preemptible',\n                                  operator='In',\n                                  values=['true'])]\n    )\n    if hard_constraint:\n      node_affinity = V1NodeAffinity(required_during_scheduling_ignored_during_execution=\n                        V1NodeSelector(node_selector_terms=[node_selector_term]))\n    else:\n      node_affinity = V1NodeAffinity(preferred_during_scheduling_ignored_during_execution=[\n                        V1PreferredSchedulingTerm(preference=node_selector_term,\n                                                  weight=50)\n      ])\n    affinity = V1Affinity(node_affinity=node_affinity)\n    task.add_affinity(affinity=affinity)\n    return task\n\n  return _set_preemptible\n\ndef add_gpu_toleration(toleration: V1Toleration = V1Toleration(\n    effect='NoSchedule', key='nvidia.com/gpu', operator='Equal', value='true')):\n    \"\"\"An operator that configures the GKE GPU nodes in a container op.\n\n    Args:\n      toleration {V1Toleration} -- toleration to pods, default is the nvidia.com/gpu label.\n    \"\"\"\n\n    def _set_toleration(task):\n        task.add_toleration(toleration)\n\n    return _set_toleration\n", "path": "sdk/python/kfp/gcp.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\nfrom kubernetes.client import V1Toleration, V1Affinity, V1NodeAffinity, \\\n  V1NodeSelector, V1NodeSelectorTerm, V1NodeSelectorRequirement, V1PreferredSchedulingTerm\n\ndef use_gcp_secret(secret_name='user-gcp-sa', secret_file_path_in_volume=None, volume_name=None, secret_volume_mount_path='/secret/gcp-credentials'):\n    \"\"\"An operator that configures the container to use GCP service account by service account key\n        stored in a Kubernetes secret.\n\n        For cluster setup and alternatives to using service account key, check https://www.kubeflow.org/docs/gke/authentication-pipelines/.\n    \"\"\"\n\n    # permitted values for secret_name = ['admin-gcp-sa', 'user-gcp-sa']\n    if secret_file_path_in_volume is None:\n        secret_file_path_in_volume = '/' + secret_name + '.json'\n\n    if volume_name is None:\n        volume_name = 'gcp-credentials-' + secret_name\n\n    else:\n        import warnings\n        warnings.warn('The volume_name parameter is deprecated and will be removed in next release. The volume names are now generated automatically.', DeprecationWarning)\n    \n    def _use_gcp_secret(task):\n        from kubernetes import client as k8s_client\n        task = task.add_volume(\n            k8s_client.V1Volume(\n                name=volume_name,\n                secret=k8s_client.V1SecretVolumeSource(\n                    secret_name=secret_name,\n                )\n            )\n        )\n        task.container \\\n            .add_volume_mount(\n                    k8s_client.V1VolumeMount(\n                        name=volume_name,\n                        mount_path=secret_volume_mount_path,\n                    )\n                ) \\\n            .add_env_variable(\n                k8s_client.V1EnvVar(\n                    name='GOOGLE_APPLICATION_CREDENTIALS',\n                    value=secret_volume_mount_path + secret_file_path_in_volume,\n                )\n            ) \\\n            .add_env_variable(\n                k8s_client.V1EnvVar(\n                    name='CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE',\n                    value=secret_volume_mount_path + secret_file_path_in_volume,\n                )\n            ) # Set GCloud Credentials by using the env var override.\n              # TODO: Is there a better way for GCloud to pick up the credential?\n        return task\n    \n    return _use_gcp_secret\n\ndef use_tpu(tpu_cores: int, tpu_resource: str, tf_version: str):\n    \"\"\"An operator that configures GCP TPU spec in a container op.\n\n    Args:\n      tpu_cores: Required. The number of cores of TPU resource. \n        For example, the value can be '8', '32', '128', etc.\n        Check more details at: https://cloud.google.com/tpu/docs/kubernetes-engine-setup#pod-spec.\n      tpu_resource: Required. The resource name of the TPU resource. \n        For example, the value can be 'v2', 'preemptible-v1', 'v3' or 'preemptible-v3'.\n        Check more details at: https://cloud.google.com/tpu/docs/kubernetes-engine-setup#pod-spec.\n      tf_version: Required. The TensorFlow version that the TPU nodes use.\n        For example, the value can be '1.12', '1.11', '1.9' or '1.8'.\n        Check more details at: https://cloud.google.com/tpu/docs/supported-versions.\n    \"\"\"\n\n    def _set_tpu_spec(task):\n        task.add_pod_annotation('tf-version.cloud-tpus.google.com', tf_version)\n        task.container.add_resource_limit('cloud-tpus.google.com/{}'.format(tpu_resource), str(tpu_cores))\n        return task\n\n    return _set_tpu_spec\n\ndef use_preemptible_nodepool(toleration: V1Toleration = V1Toleration(effect='NoSchedule',\n                                                             key='preemptible',\n                                                             operator='Equal',\n                                                             value='true'),\n                              hard_constraint: bool = False):\n  \"\"\"An operator that configures the GKE preemptible in a container op.\n  Args:\n    toleration (V1Toleration): toleration to pods, default is the preemptible label.\n    hard_constraint (bool): the constraint of scheduling the pods on preemptible\n        nodepools is hard. (Default: False)\n  \"\"\"\n\n  def _set_preemptible(task):\n    task.add_toleration(toleration)\n    node_selector_term = V1NodeSelectorTerm(match_expressions=[\n        V1NodeSelectorRequirement(key='cloud.google.com/gke-preemptible',\n                                  operator='In',\n                                  values=['true'])]\n    )\n    if hard_constraint:\n      node_affinity = V1NodeAffinity(required_during_scheduling_ignored_during_execution=\n                        V1NodeSelector(node_selector_terms=[node_selector_term]))\n    else:\n      node_affinity = V1NodeAffinity(preferred_during_scheduling_ignored_during_execution=[\n                        V1PreferredSchedulingTerm(preference=node_selector_term,\n                                                  weight=50)\n      ])\n    affinity = V1Affinity(node_affinity=node_affinity)\n    task.add_affinity(affinity=affinity)\n    return task\n\n  return _set_preemptible\n\ndef add_gpu_toleration(toleration: V1Toleration = V1Toleration(\n    effect='NoSchedule', key='nvidia.com/gpu', operator='Equal', value='true')):\n    \"\"\"An operator that configures the GKE GPU nodes in a container op.\n\n    Args:\n      toleration {V1Toleration} -- toleration to pods, default is the nvidia.com/gpu label.\n    \"\"\"\n\n    def _set_toleration(task):\n        task.add_toleration(toleration)\n\n    return _set_toleration\n", "path": "sdk/python/kfp/gcp.py"}]}