We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
'kubeflow-pipelines-profile-controller' fails to deploy pods on profile creation when ResourceQuota is set in the profile.
In multi-user mode, it seems like `kubeflow-pipelines-profile-controller` deploy below pods on Kubeflow profile creation.

- `ml-pipeline-ui-artifact`
- `ml-pipeline-visualizationserver`

When `ResourceQuota` is set in the profile, `kubeflow-pipelines-profile-controller` fails to deploy `ml-pipeline-ui-artifact` and `ml-pipeline-visualizationserver` with below error.

```
Warning  FailedCreate  17m replicaset-controller 
Error creating: pods "ml-pipeline-ui-artifact-684c5db68-s74w8" is forbidden: failed quota: kf-resource-quota: must specify cpu,memory
```

- Related code: [https://github.com/kubeflow/manifests/blob/master/apps/pipeline/upstream/installs/multi-user/pipelines-profile-controller/sync.py](https://github.com/kubeflow/manifests/blob/master/apps/pipeline/upstream/installs/multi-user/pipelines-profile-controller/sync.py)
- Cause: The container resource limit & request is not set on the pod specs, so the pods can not be deployed in the namespace (which has  `ResourceQuota` ).

Since Kubeflow profile supports setting `ResourceQuota`,  `kubeflow-pipelines-profile-controller` should set container resource requests & limits in pod specs to avoid above errors. 

I confirmed that with below patch, ml-pipeline pods are successfully deployed.

```python
diff --git a/apps/pipeline/upstream/installs/multi-user/pipelines-profile-controller/sync.py b/apps/pipeline/upstream/installs/multi-user/pipelines-profile-controller/sync.py
index 75c6e5db..a0e71fbf 100644
--- a/apps/pipeline/upstream/installs/multi-user/pipelines-profile-controller/sync.py
+++ b/apps/pipeline/upstream/installs/multi-user/pipelines-profile-controller/sync.py
@@ -104,6 +104,16 @@ class Controller(BaseHTTPRequestHandler):
                                 "ports": [{
                                     "containerPort": 8888
                                 }],
+                                "resources": {
+                                    "requests": {
+                                        "cpu": "50m",
+                                        "memory": "200Mi"
+                                    },
+                                    "limits": {
+                                        "cpu": "500m",
+                                        "memory": "2Gi"
+                                    },
+                                }
                             }],
                             "serviceAccountName":
                             "default-editor",
@@ -204,7 +214,17 @@ class Controller(BaseHTTPRequestHandler):
                                 "IfNotPresent",
                                 "ports": [{
                                     "containerPort": 3000
-                                }]
+                                }],
+                                "resources": {
+                                    "requests": {
+                                        "cpu": "50m",
+                                        "memory": "200Mi"
+                                    },
+                                    "limits": {
+                                        "cpu": "500m",
+                                        "memory": "2Gi"
+                                    },
+                                }
                             }],
                             "serviceAccountName":
                             "default-editor"
```

Please take a look, thanks.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `manifests/kustomize/base/installs/multi-user/pipelines-profile-controller/sync.py`
Content:
```
1 # Copyright 2020 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 http.server import BaseHTTPRequestHandler, HTTPServer
16 import json
17 import os
18 import base64
19 
20 kfp_version = os.environ["KFP_VERSION"]
21 disable_istio_sidecar = os.environ.get("DISABLE_ISTIO_SIDECAR") == "true"
22 mlpipeline_minio_access_key = base64.b64encode(
23     bytes(os.environ.get("MINIO_ACCESS_KEY"), 'utf-8')).decode('utf-8')
24 mlpipeline_minio_secret_key = base64.b64encode(
25     bytes(os.environ.get("MINIO_SECRET_KEY"), 'utf-8')).decode('utf-8')
26 
27 
28 class Controller(BaseHTTPRequestHandler):
29     def sync(self, parent, children):
30         # HACK: Currently using serving.kubeflow.org/inferenceservice to identify
31         # kubeflow user namespaces.
32         # TODO: let Kubeflow profile controller add a pipeline specific label to
33         # user namespaces and use that label instead.
34         pipeline_enabled = parent.get("metadata", {}).get(
35             "labels", {}).get("serving.kubeflow.org/inferenceservice")
36 
37         if not pipeline_enabled:
38             return {"status": {}, "children": []}
39 
40         # Compute status based on observed state.
41         desired_status = {
42             "kubeflow-pipelines-ready": \
43                 len(children["Secret.v1"]) == 1 and \
44                 len(children["ConfigMap.v1"]) == 1 and \
45                 len(children["Deployment.apps/v1"]) == 2 and \
46                 len(children["Service.v1"]) == 2 and \
47                 len(children["DestinationRule.networking.istio.io/v1alpha3"]) == 1 and \
48                 len(children["AuthorizationPolicy.security.istio.io/v1beta1"]) == 1 and \
49                 "True" or "False"
50         }
51 
52         # Generate the desired child object(s).
53         # parent is a namespace
54         namespace = parent.get("metadata", {}).get("name")
55         desired_resources = [
56             {
57                 "apiVersion": "v1",
58                 "kind": "ConfigMap",
59                 "metadata": {
60                     "name": "metadata-grpc-configmap",
61                     "namespace": namespace,
62                 },
63                 "data": {
64                     "METADATA_GRPC_SERVICE_HOST":
65                     "metadata-grpc-service.kubeflow",
66                     "METADATA_GRPC_SERVICE_PORT": "8080",
67                 },
68             },
69             # Visualization server related manifests below
70             {
71                 "apiVersion": "apps/v1",
72                 "kind": "Deployment",
73                 "metadata": {
74                     "labels": {
75                         "app": "ml-pipeline-visualizationserver"
76                     },
77                     "name": "ml-pipeline-visualizationserver",
78                     "namespace": namespace,
79                 },
80                 "spec": {
81                     "selector": {
82                         "matchLabels": {
83                             "app": "ml-pipeline-visualizationserver"
84                         },
85                     },
86                     "template": {
87                         "metadata": {
88                             "labels": {
89                                 "app": "ml-pipeline-visualizationserver"
90                             },
91                             "annotations": disable_istio_sidecar and {
92                                 "sidecar.istio.io/inject": "false"
93                             } or {},
94                         },
95                         "spec": {
96                             "containers": [{
97                                 "image":
98                                 "gcr.io/ml-pipeline/visualization-server:" +
99                                 kfp_version,
100                                 "imagePullPolicy":
101                                 "IfNotPresent",
102                                 "name":
103                                 "ml-pipeline-visualizationserver",
104                                 "ports": [{
105                                     "containerPort": 8888
106                                 }],
107                             }],
108                             "serviceAccountName":
109                             "default-editor",
110                         },
111                     },
112                 },
113             },
114             {
115                 "apiVersion": "networking.istio.io/v1alpha3",
116                 "kind": "DestinationRule",
117                 "metadata": {
118                     "name": "ml-pipeline-visualizationserver",
119                     "namespace": namespace,
120                 },
121                 "spec": {
122                     "host": "ml-pipeline-visualizationserver",
123                     "trafficPolicy": {
124                         "tls": {
125                             "mode": "ISTIO_MUTUAL"
126                         }
127                     }
128                 }
129             },
130             {
131                 "apiVersion": "security.istio.io/v1beta1",
132                 "kind": "AuthorizationPolicy",
133                 "metadata": {
134                     "name": "ml-pipeline-visualizationserver",
135                     "namespace": namespace,
136                 },
137                 "spec": {
138                     "selector": {
139                         "matchLabels": {
140                             "app": "ml-pipeline-visualizationserver"
141                         }
142                     },
143                     "rules": [{
144                         "from": [{
145                             "source": {
146                                 "principals": ["cluster.local/ns/kubeflow/sa/ml-pipeline"]
147                             }
148                         }]
149                     }]
150                 }
151             },
152             {
153                 "apiVersion": "v1",
154                 "kind": "Service",
155                 "metadata": {
156                     "name": "ml-pipeline-visualizationserver",
157                     "namespace": namespace,
158                 },
159                 "spec": {
160                     "ports": [{
161                         "name": "http",
162                         "port": 8888,
163                         "protocol": "TCP",
164                         "targetPort": 8888,
165                     }],
166                     "selector": {
167                         "app": "ml-pipeline-visualizationserver",
168                     },
169                 },
170             },
171             # Artifact fetcher related resources below.
172             {
173                 "apiVersion": "apps/v1",
174                 "kind": "Deployment",
175                 "metadata": {
176                     "labels": {
177                         "app": "ml-pipeline-ui-artifact"
178                     },
179                     "name": "ml-pipeline-ui-artifact",
180                     "namespace": namespace,
181                 },
182                 "spec": {
183                     "selector": {
184                         "matchLabels": {
185                             "app": "ml-pipeline-ui-artifact"
186                         }
187                     },
188                     "template": {
189                         "metadata": {
190                             "labels": {
191                                 "app": "ml-pipeline-ui-artifact"
192                             },
193                             "annotations": disable_istio_sidecar and {
194                                 "sidecar.istio.io/inject": "false"
195                             } or {},
196                         },
197                         "spec": {
198                             "containers": [{
199                                 "name":
200                                 "ml-pipeline-ui-artifact",
201                                 "image":
202                                 "gcr.io/ml-pipeline/frontend:" + kfp_version,
203                                 "imagePullPolicy":
204                                 "IfNotPresent",
205                                 "ports": [{
206                                     "containerPort": 3000
207                                 }]
208                             }],
209                             "serviceAccountName":
210                             "default-editor"
211                         }
212                     }
213                 }
214             },
215             {
216                 "apiVersion": "v1",
217                 "kind": "Service",
218                 "metadata": {
219                     "name": "ml-pipeline-ui-artifact",
220                     "namespace": namespace,
221                     "labels": {
222                         "app": "ml-pipeline-ui-artifact"
223                     }
224                 },
225                 "spec": {
226                     "ports": [{
227                         "name":
228                         "http",  # name is required to let istio understand request protocol
229                         "port": 80,
230                         "protocol": "TCP",
231                         "targetPort": 3000
232                     }],
233                     "selector": {
234                         "app": "ml-pipeline-ui-artifact"
235                     }
236                 }
237             },
238         ]
239         print('Received request:', parent)
240         print('Desired resources except secrets:', desired_resources)
241         # Moved after the print argument because this is sensitive data.
242         desired_resources.append({
243             "apiVersion": "v1",
244             "kind": "Secret",
245             "metadata": {
246                 "name": "mlpipeline-minio-artifact",
247                 "namespace": namespace,
248             },
249             "data": {
250                 "accesskey": mlpipeline_minio_access_key,
251                 "secretkey": mlpipeline_minio_secret_key,
252             },
253         })
254 
255         return {"status": desired_status, "children": desired_resources}
256 
257     def do_POST(self):
258         # Serve the sync() function as a JSON webhook.
259         observed = json.loads(
260             self.rfile.read(int(self.headers.get("content-length"))))
261         desired = self.sync(observed["parent"], observed["children"])
262 
263         self.send_response(200)
264         self.send_header("Content-type", "application/json")
265         self.end_headers()
266         self.wfile.write(bytes(json.dumps(desired), 'utf-8'))
267 
268 
269 HTTPServer(("", 80), Controller).serve_forever()
270
```
--- 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/manifests/kustomize/base/installs/multi-user/pipelines-profile-controller/sync.py b/manifests/kustomize/base/installs/multi-user/pipelines-profile-controller/sync.py
--- a/manifests/kustomize/base/installs/multi-user/pipelines-profile-controller/sync.py
+++ b/manifests/kustomize/base/installs/multi-user/pipelines-profile-controller/sync.py
@@ -104,6 +104,16 @@
                                 "ports": [{
                                     "containerPort": 8888
                                 }],
+                                "resources": {
+                                    "requests": {
+                                        "cpu": "50m",
+                                        "memory": "200Mi"
+                                    },
+                                    "limits": {
+                                        "cpu": "500m",
+                                        "memory": "1Gi"
+                                    },
+                                }
                             }],
                             "serviceAccountName":
                             "default-editor",
@@ -204,7 +214,17 @@
                                 "IfNotPresent",
                                 "ports": [{
                                     "containerPort": 3000
-                                }]
+                                }],
+                                "resources": {
+                                    "requests": {
+                                        "cpu": "10m",
+                                        "memory": "70Mi"
+                                    },
+                                    "limits": {
+                                        "cpu": "100m",
+                                        "memory": "500Mi"
+                                    },
+                                }
                             }],
                             "serviceAccountName":
                             "default-editor"

{"golden_diff": "diff --git a/manifests/kustomize/base/installs/multi-user/pipelines-profile-controller/sync.py b/manifests/kustomize/base/installs/multi-user/pipelines-profile-controller/sync.py\n--- a/manifests/kustomize/base/installs/multi-user/pipelines-profile-controller/sync.py\n+++ b/manifests/kustomize/base/installs/multi-user/pipelines-profile-controller/sync.py\n@@ -104,6 +104,16 @@\n                                 \"ports\": [{\n                                     \"containerPort\": 8888\n                                 }],\n+                                \"resources\": {\n+                                    \"requests\": {\n+                                        \"cpu\": \"50m\",\n+                                        \"memory\": \"200Mi\"\n+                                    },\n+                                    \"limits\": {\n+                                        \"cpu\": \"500m\",\n+                                        \"memory\": \"1Gi\"\n+                                    },\n+                                }\n                             }],\n                             \"serviceAccountName\":\n                             \"default-editor\",\n@@ -204,7 +214,17 @@\n                                 \"IfNotPresent\",\n                                 \"ports\": [{\n                                     \"containerPort\": 3000\n-                                }]\n+                                }],\n+                                \"resources\": {\n+                                    \"requests\": {\n+                                        \"cpu\": \"10m\",\n+                                        \"memory\": \"70Mi\"\n+                                    },\n+                                    \"limits\": {\n+                                        \"cpu\": \"100m\",\n+                                        \"memory\": \"500Mi\"\n+                                    },\n+                                }\n                             }],\n                             \"serviceAccountName\":\n                             \"default-editor\"\n", "issue": "'kubeflow-pipelines-profile-controller' fails to deploy pods on profile creation when ResourceQuota is set in the profile.\nIn multi-user mode, it seems like `kubeflow-pipelines-profile-controller` deploy below pods on Kubeflow profile creation.\r\n\r\n- `ml-pipeline-ui-artifact`\r\n- `ml-pipeline-visualizationserver`\r\n\r\nWhen `ResourceQuota` is set in the profile, `kubeflow-pipelines-profile-controller` fails to deploy `ml-pipeline-ui-artifact` and `ml-pipeline-visualizationserver` with below error.\r\n\r\n```\r\nWarning  FailedCreate  17m replicaset-controller \r\nError creating: pods \"ml-pipeline-ui-artifact-684c5db68-s74w8\" is forbidden: failed quota: kf-resource-quota: must specify cpu,memory\r\n```\r\n\r\n- Related code: [https://github.com/kubeflow/manifests/blob/master/apps/pipeline/upstream/installs/multi-user/pipelines-profile-controller/sync.py](https://github.com/kubeflow/manifests/blob/master/apps/pipeline/upstream/installs/multi-user/pipelines-profile-controller/sync.py)\r\n- Cause: The container resource limit & request is not set on the pod specs, so the pods can not be deployed in the namespace (which has  `ResourceQuota` ).\r\n\r\nSince Kubeflow profile supports setting `ResourceQuota`,  `kubeflow-pipelines-profile-controller` should set container resource requests & limits in pod specs to avoid above errors. \r\n\r\nI confirmed that with below patch, ml-pipeline pods are successfully deployed.\r\n\r\n```python\r\ndiff --git a/apps/pipeline/upstream/installs/multi-user/pipelines-profile-controller/sync.py b/apps/pipeline/upstream/installs/multi-user/pipelines-profile-controller/sync.py\r\nindex 75c6e5db..a0e71fbf 100644\r\n--- a/apps/pipeline/upstream/installs/multi-user/pipelines-profile-controller/sync.py\r\n+++ b/apps/pipeline/upstream/installs/multi-user/pipelines-profile-controller/sync.py\r\n@@ -104,6 +104,16 @@ class Controller(BaseHTTPRequestHandler):\r\n                                 \"ports\": [{\r\n                                     \"containerPort\": 8888\r\n                                 }],\r\n+                                \"resources\": {\r\n+                                    \"requests\": {\r\n+                                        \"cpu\": \"50m\",\r\n+                                        \"memory\": \"200Mi\"\r\n+                                    },\r\n+                                    \"limits\": {\r\n+                                        \"cpu\": \"500m\",\r\n+                                        \"memory\": \"2Gi\"\r\n+                                    },\r\n+                                }\r\n                             }],\r\n                             \"serviceAccountName\":\r\n                             \"default-editor\",\r\n@@ -204,7 +214,17 @@ class Controller(BaseHTTPRequestHandler):\r\n                                 \"IfNotPresent\",\r\n                                 \"ports\": [{\r\n                                     \"containerPort\": 3000\r\n-                                }]\r\n+                                }],\r\n+                                \"resources\": {\r\n+                                    \"requests\": {\r\n+                                        \"cpu\": \"50m\",\r\n+                                        \"memory\": \"200Mi\"\r\n+                                    },\r\n+                                    \"limits\": {\r\n+                                        \"cpu\": \"500m\",\r\n+                                        \"memory\": \"2Gi\"\r\n+                                    },\r\n+                                }\r\n                             }],\r\n                             \"serviceAccountName\":\r\n                             \"default-editor\"\r\n```\r\n\r\nPlease take a look, thanks.\n", "before_files": [{"content": "# Copyright 2020 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 http.server import BaseHTTPRequestHandler, HTTPServer\nimport json\nimport os\nimport base64\n\nkfp_version = os.environ[\"KFP_VERSION\"]\ndisable_istio_sidecar = os.environ.get(\"DISABLE_ISTIO_SIDECAR\") == \"true\"\nmlpipeline_minio_access_key = base64.b64encode(\n    bytes(os.environ.get(\"MINIO_ACCESS_KEY\"), 'utf-8')).decode('utf-8')\nmlpipeline_minio_secret_key = base64.b64encode(\n    bytes(os.environ.get(\"MINIO_SECRET_KEY\"), 'utf-8')).decode('utf-8')\n\n\nclass Controller(BaseHTTPRequestHandler):\n    def sync(self, parent, children):\n        # HACK: Currently using serving.kubeflow.org/inferenceservice to identify\n        # kubeflow user namespaces.\n        # TODO: let Kubeflow profile controller add a pipeline specific label to\n        # user namespaces and use that label instead.\n        pipeline_enabled = parent.get(\"metadata\", {}).get(\n            \"labels\", {}).get(\"serving.kubeflow.org/inferenceservice\")\n\n        if not pipeline_enabled:\n            return {\"status\": {}, \"children\": []}\n\n        # Compute status based on observed state.\n        desired_status = {\n            \"kubeflow-pipelines-ready\": \\\n                len(children[\"Secret.v1\"]) == 1 and \\\n                len(children[\"ConfigMap.v1\"]) == 1 and \\\n                len(children[\"Deployment.apps/v1\"]) == 2 and \\\n                len(children[\"Service.v1\"]) == 2 and \\\n                len(children[\"DestinationRule.networking.istio.io/v1alpha3\"]) == 1 and \\\n                len(children[\"AuthorizationPolicy.security.istio.io/v1beta1\"]) == 1 and \\\n                \"True\" or \"False\"\n        }\n\n        # Generate the desired child object(s).\n        # parent is a namespace\n        namespace = parent.get(\"metadata\", {}).get(\"name\")\n        desired_resources = [\n            {\n                \"apiVersion\": \"v1\",\n                \"kind\": \"ConfigMap\",\n                \"metadata\": {\n                    \"name\": \"metadata-grpc-configmap\",\n                    \"namespace\": namespace,\n                },\n                \"data\": {\n                    \"METADATA_GRPC_SERVICE_HOST\":\n                    \"metadata-grpc-service.kubeflow\",\n                    \"METADATA_GRPC_SERVICE_PORT\": \"8080\",\n                },\n            },\n            # Visualization server related manifests below\n            {\n                \"apiVersion\": \"apps/v1\",\n                \"kind\": \"Deployment\",\n                \"metadata\": {\n                    \"labels\": {\n                        \"app\": \"ml-pipeline-visualizationserver\"\n                    },\n                    \"name\": \"ml-pipeline-visualizationserver\",\n                    \"namespace\": namespace,\n                },\n                \"spec\": {\n                    \"selector\": {\n                        \"matchLabels\": {\n                            \"app\": \"ml-pipeline-visualizationserver\"\n                        },\n                    },\n                    \"template\": {\n                        \"metadata\": {\n                            \"labels\": {\n                                \"app\": \"ml-pipeline-visualizationserver\"\n                            },\n                            \"annotations\": disable_istio_sidecar and {\n                                \"sidecar.istio.io/inject\": \"false\"\n                            } or {},\n                        },\n                        \"spec\": {\n                            \"containers\": [{\n                                \"image\":\n                                \"gcr.io/ml-pipeline/visualization-server:\" +\n                                kfp_version,\n                                \"imagePullPolicy\":\n                                \"IfNotPresent\",\n                                \"name\":\n                                \"ml-pipeline-visualizationserver\",\n                                \"ports\": [{\n                                    \"containerPort\": 8888\n                                }],\n                            }],\n                            \"serviceAccountName\":\n                            \"default-editor\",\n                        },\n                    },\n                },\n            },\n            {\n                \"apiVersion\": \"networking.istio.io/v1alpha3\",\n                \"kind\": \"DestinationRule\",\n                \"metadata\": {\n                    \"name\": \"ml-pipeline-visualizationserver\",\n                    \"namespace\": namespace,\n                },\n                \"spec\": {\n                    \"host\": \"ml-pipeline-visualizationserver\",\n                    \"trafficPolicy\": {\n                        \"tls\": {\n                            \"mode\": \"ISTIO_MUTUAL\"\n                        }\n                    }\n                }\n            },\n            {\n                \"apiVersion\": \"security.istio.io/v1beta1\",\n                \"kind\": \"AuthorizationPolicy\",\n                \"metadata\": {\n                    \"name\": \"ml-pipeline-visualizationserver\",\n                    \"namespace\": namespace,\n                },\n                \"spec\": {\n                    \"selector\": {\n                        \"matchLabels\": {\n                            \"app\": \"ml-pipeline-visualizationserver\"\n                        }\n                    },\n                    \"rules\": [{\n                        \"from\": [{\n                            \"source\": {\n                                \"principals\": [\"cluster.local/ns/kubeflow/sa/ml-pipeline\"]\n                            }\n                        }]\n                    }]\n                }\n            },\n            {\n                \"apiVersion\": \"v1\",\n                \"kind\": \"Service\",\n                \"metadata\": {\n                    \"name\": \"ml-pipeline-visualizationserver\",\n                    \"namespace\": namespace,\n                },\n                \"spec\": {\n                    \"ports\": [{\n                        \"name\": \"http\",\n                        \"port\": 8888,\n                        \"protocol\": \"TCP\",\n                        \"targetPort\": 8888,\n                    }],\n                    \"selector\": {\n                        \"app\": \"ml-pipeline-visualizationserver\",\n                    },\n                },\n            },\n            # Artifact fetcher related resources below.\n            {\n                \"apiVersion\": \"apps/v1\",\n                \"kind\": \"Deployment\",\n                \"metadata\": {\n                    \"labels\": {\n                        \"app\": \"ml-pipeline-ui-artifact\"\n                    },\n                    \"name\": \"ml-pipeline-ui-artifact\",\n                    \"namespace\": namespace,\n                },\n                \"spec\": {\n                    \"selector\": {\n                        \"matchLabels\": {\n                            \"app\": \"ml-pipeline-ui-artifact\"\n                        }\n                    },\n                    \"template\": {\n                        \"metadata\": {\n                            \"labels\": {\n                                \"app\": \"ml-pipeline-ui-artifact\"\n                            },\n                            \"annotations\": disable_istio_sidecar and {\n                                \"sidecar.istio.io/inject\": \"false\"\n                            } or {},\n                        },\n                        \"spec\": {\n                            \"containers\": [{\n                                \"name\":\n                                \"ml-pipeline-ui-artifact\",\n                                \"image\":\n                                \"gcr.io/ml-pipeline/frontend:\" + kfp_version,\n                                \"imagePullPolicy\":\n                                \"IfNotPresent\",\n                                \"ports\": [{\n                                    \"containerPort\": 3000\n                                }]\n                            }],\n                            \"serviceAccountName\":\n                            \"default-editor\"\n                        }\n                    }\n                }\n            },\n            {\n                \"apiVersion\": \"v1\",\n                \"kind\": \"Service\",\n                \"metadata\": {\n                    \"name\": \"ml-pipeline-ui-artifact\",\n                    \"namespace\": namespace,\n                    \"labels\": {\n                        \"app\": \"ml-pipeline-ui-artifact\"\n                    }\n                },\n                \"spec\": {\n                    \"ports\": [{\n                        \"name\":\n                        \"http\",  # name is required to let istio understand request protocol\n                        \"port\": 80,\n                        \"protocol\": \"TCP\",\n                        \"targetPort\": 3000\n                    }],\n                    \"selector\": {\n                        \"app\": \"ml-pipeline-ui-artifact\"\n                    }\n                }\n            },\n        ]\n        print('Received request:', parent)\n        print('Desired resources except secrets:', desired_resources)\n        # Moved after the print argument because this is sensitive data.\n        desired_resources.append({\n            \"apiVersion\": \"v1\",\n            \"kind\": \"Secret\",\n            \"metadata\": {\n                \"name\": \"mlpipeline-minio-artifact\",\n                \"namespace\": namespace,\n            },\n            \"data\": {\n                \"accesskey\": mlpipeline_minio_access_key,\n                \"secretkey\": mlpipeline_minio_secret_key,\n            },\n        })\n\n        return {\"status\": desired_status, \"children\": desired_resources}\n\n    def do_POST(self):\n        # Serve the sync() function as a JSON webhook.\n        observed = json.loads(\n            self.rfile.read(int(self.headers.get(\"content-length\"))))\n        desired = self.sync(observed[\"parent\"], observed[\"children\"])\n\n        self.send_response(200)\n        self.send_header(\"Content-type\", \"application/json\")\n        self.end_headers()\n        self.wfile.write(bytes(json.dumps(desired), 'utf-8'))\n\n\nHTTPServer((\"\", 80), Controller).serve_forever()\n", "path": "manifests/kustomize/base/installs/multi-user/pipelines-profile-controller/sync.py"}], "after_files": [{"content": "# Copyright 2020 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 http.server import BaseHTTPRequestHandler, HTTPServer\nimport json\nimport os\nimport base64\n\nkfp_version = os.environ[\"KFP_VERSION\"]\ndisable_istio_sidecar = os.environ.get(\"DISABLE_ISTIO_SIDECAR\") == \"true\"\nmlpipeline_minio_access_key = base64.b64encode(\n    bytes(os.environ.get(\"MINIO_ACCESS_KEY\"), 'utf-8')).decode('utf-8')\nmlpipeline_minio_secret_key = base64.b64encode(\n    bytes(os.environ.get(\"MINIO_SECRET_KEY\"), 'utf-8')).decode('utf-8')\n\n\nclass Controller(BaseHTTPRequestHandler):\n    def sync(self, parent, children):\n        # HACK: Currently using serving.kubeflow.org/inferenceservice to identify\n        # kubeflow user namespaces.\n        # TODO: let Kubeflow profile controller add a pipeline specific label to\n        # user namespaces and use that label instead.\n        pipeline_enabled = parent.get(\"metadata\", {}).get(\n            \"labels\", {}).get(\"serving.kubeflow.org/inferenceservice\")\n\n        if not pipeline_enabled:\n            return {\"status\": {}, \"children\": []}\n\n        # Compute status based on observed state.\n        desired_status = {\n            \"kubeflow-pipelines-ready\": \\\n                len(children[\"Secret.v1\"]) == 1 and \\\n                len(children[\"ConfigMap.v1\"]) == 1 and \\\n                len(children[\"Deployment.apps/v1\"]) == 2 and \\\n                len(children[\"Service.v1\"]) == 2 and \\\n                len(children[\"DestinationRule.networking.istio.io/v1alpha3\"]) == 1 and \\\n                len(children[\"AuthorizationPolicy.security.istio.io/v1beta1\"]) == 1 and \\\n                \"True\" or \"False\"\n        }\n\n        # Generate the desired child object(s).\n        # parent is a namespace\n        namespace = parent.get(\"metadata\", {}).get(\"name\")\n        desired_resources = [\n            {\n                \"apiVersion\": \"v1\",\n                \"kind\": \"ConfigMap\",\n                \"metadata\": {\n                    \"name\": \"metadata-grpc-configmap\",\n                    \"namespace\": namespace,\n                },\n                \"data\": {\n                    \"METADATA_GRPC_SERVICE_HOST\":\n                    \"metadata-grpc-service.kubeflow\",\n                    \"METADATA_GRPC_SERVICE_PORT\": \"8080\",\n                },\n            },\n            # Visualization server related manifests below\n            {\n                \"apiVersion\": \"apps/v1\",\n                \"kind\": \"Deployment\",\n                \"metadata\": {\n                    \"labels\": {\n                        \"app\": \"ml-pipeline-visualizationserver\"\n                    },\n                    \"name\": \"ml-pipeline-visualizationserver\",\n                    \"namespace\": namespace,\n                },\n                \"spec\": {\n                    \"selector\": {\n                        \"matchLabels\": {\n                            \"app\": \"ml-pipeline-visualizationserver\"\n                        },\n                    },\n                    \"template\": {\n                        \"metadata\": {\n                            \"labels\": {\n                                \"app\": \"ml-pipeline-visualizationserver\"\n                            },\n                            \"annotations\": disable_istio_sidecar and {\n                                \"sidecar.istio.io/inject\": \"false\"\n                            } or {},\n                        },\n                        \"spec\": {\n                            \"containers\": [{\n                                \"image\":\n                                \"gcr.io/ml-pipeline/visualization-server:\" +\n                                kfp_version,\n                                \"imagePullPolicy\":\n                                \"IfNotPresent\",\n                                \"name\":\n                                \"ml-pipeline-visualizationserver\",\n                                \"ports\": [{\n                                    \"containerPort\": 8888\n                                }],\n                                \"resources\": {\n                                    \"requests\": {\n                                        \"cpu\": \"50m\",\n                                        \"memory\": \"200Mi\"\n                                    },\n                                    \"limits\": {\n                                        \"cpu\": \"500m\",\n                                        \"memory\": \"1Gi\"\n                                    },\n                                }\n                            }],\n                            \"serviceAccountName\":\n                            \"default-editor\",\n                        },\n                    },\n                },\n            },\n            {\n                \"apiVersion\": \"networking.istio.io/v1alpha3\",\n                \"kind\": \"DestinationRule\",\n                \"metadata\": {\n                    \"name\": \"ml-pipeline-visualizationserver\",\n                    \"namespace\": namespace,\n                },\n                \"spec\": {\n                    \"host\": \"ml-pipeline-visualizationserver\",\n                    \"trafficPolicy\": {\n                        \"tls\": {\n                            \"mode\": \"ISTIO_MUTUAL\"\n                        }\n                    }\n                }\n            },\n            {\n                \"apiVersion\": \"security.istio.io/v1beta1\",\n                \"kind\": \"AuthorizationPolicy\",\n                \"metadata\": {\n                    \"name\": \"ml-pipeline-visualizationserver\",\n                    \"namespace\": namespace,\n                },\n                \"spec\": {\n                    \"selector\": {\n                        \"matchLabels\": {\n                            \"app\": \"ml-pipeline-visualizationserver\"\n                        }\n                    },\n                    \"rules\": [{\n                        \"from\": [{\n                            \"source\": {\n                                \"principals\": [\"cluster.local/ns/kubeflow/sa/ml-pipeline\"]\n                            }\n                        }]\n                    }]\n                }\n            },\n            {\n                \"apiVersion\": \"v1\",\n                \"kind\": \"Service\",\n                \"metadata\": {\n                    \"name\": \"ml-pipeline-visualizationserver\",\n                    \"namespace\": namespace,\n                },\n                \"spec\": {\n                    \"ports\": [{\n                        \"name\": \"http\",\n                        \"port\": 8888,\n                        \"protocol\": \"TCP\",\n                        \"targetPort\": 8888,\n                    }],\n                    \"selector\": {\n                        \"app\": \"ml-pipeline-visualizationserver\",\n                    },\n                },\n            },\n            # Artifact fetcher related resources below.\n            {\n                \"apiVersion\": \"apps/v1\",\n                \"kind\": \"Deployment\",\n                \"metadata\": {\n                    \"labels\": {\n                        \"app\": \"ml-pipeline-ui-artifact\"\n                    },\n                    \"name\": \"ml-pipeline-ui-artifact\",\n                    \"namespace\": namespace,\n                },\n                \"spec\": {\n                    \"selector\": {\n                        \"matchLabels\": {\n                            \"app\": \"ml-pipeline-ui-artifact\"\n                        }\n                    },\n                    \"template\": {\n                        \"metadata\": {\n                            \"labels\": {\n                                \"app\": \"ml-pipeline-ui-artifact\"\n                            },\n                            \"annotations\": disable_istio_sidecar and {\n                                \"sidecar.istio.io/inject\": \"false\"\n                            } or {},\n                        },\n                        \"spec\": {\n                            \"containers\": [{\n                                \"name\":\n                                \"ml-pipeline-ui-artifact\",\n                                \"image\":\n                                \"gcr.io/ml-pipeline/frontend:\" + kfp_version,\n                                \"imagePullPolicy\":\n                                \"IfNotPresent\",\n                                \"ports\": [{\n                                    \"containerPort\": 3000\n                                }],\n                                \"resources\": {\n                                    \"requests\": {\n                                        \"cpu\": \"10m\",\n                                        \"memory\": \"70Mi\"\n                                    },\n                                    \"limits\": {\n                                        \"cpu\": \"100m\",\n                                        \"memory\": \"500Mi\"\n                                    },\n                                }\n                            }],\n                            \"serviceAccountName\":\n                            \"default-editor\"\n                        }\n                    }\n                }\n            },\n            {\n                \"apiVersion\": \"v1\",\n                \"kind\": \"Service\",\n                \"metadata\": {\n                    \"name\": \"ml-pipeline-ui-artifact\",\n                    \"namespace\": namespace,\n                    \"labels\": {\n                        \"app\": \"ml-pipeline-ui-artifact\"\n                    }\n                },\n                \"spec\": {\n                    \"ports\": [{\n                        \"name\":\n                        \"http\",  # name is required to let istio understand request protocol\n                        \"port\": 80,\n                        \"protocol\": \"TCP\",\n                        \"targetPort\": 3000\n                    }],\n                    \"selector\": {\n                        \"app\": \"ml-pipeline-ui-artifact\"\n                    }\n                }\n            },\n        ]\n        print('Received request:', parent)\n        print('Desired resources except secrets:', desired_resources)\n        # Moved after the print argument because this is sensitive data.\n        desired_resources.append({\n            \"apiVersion\": \"v1\",\n            \"kind\": \"Secret\",\n            \"metadata\": {\n                \"name\": \"mlpipeline-minio-artifact\",\n                \"namespace\": namespace,\n            },\n            \"data\": {\n                \"accesskey\": mlpipeline_minio_access_key,\n                \"secretkey\": mlpipeline_minio_secret_key,\n            },\n        })\n\n        return {\"status\": desired_status, \"children\": desired_resources}\n\n    def do_POST(self):\n        # Serve the sync() function as a JSON webhook.\n        observed = json.loads(\n            self.rfile.read(int(self.headers.get(\"content-length\"))))\n        desired = self.sync(observed[\"parent\"], observed[\"children\"])\n\n        self.send_response(200)\n        self.send_header(\"Content-type\", \"application/json\")\n        self.end_headers()\n        self.wfile.write(bytes(json.dumps(desired), 'utf-8'))\n\n\nHTTPServer((\"\", 80), Controller).serve_forever()\n", "path": "manifests/kustomize/base/installs/multi-user/pipelines-profile-controller/sync.py"}]}