We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
json files created by provision are not human readable


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `nvflare/lighter/impl/static_file.py`
Content:
```
1 # Copyright (c) 2021-2022, NVIDIA CORPORATION.  All rights reserved.
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 copy
16 import json
17 import os
18 
19 import yaml
20 
21 from nvflare.lighter.spec import Builder
22 from nvflare.lighter.utils import sh_replace
23 
24 
25 class StaticFileBuilder(Builder):
26     def __init__(
27         self,
28         enable_byoc=False,
29         config_folder="",
30         app_validator="",
31         docker_image="",
32         snapshot_persistor="",
33         overseer_agent="",
34     ):
35         """Build all static files from template.
36 
37         Uses the information from project.yml through study to go through the participants and write the contents of
38         each file with the template, and replacing with the appropriate values from project.yml.
39 
40         Usually, two main categories of files are created in all FL participants, static and dynamic. Static files
41         have similar contents among different participants, with small differences.  For example, the differences in
42         sub_start.sh are client name and python module.  Those are basically static files.  This builder uses template
43         file and string replacement to generate those static files for each participant.
44 
45         Args:
46             enable_byoc: for each participant, true to enable loading of code in the custom folder of applications
47             config_folder: usually "config"
48             app_validator: optional path to an app validator to verify that uploaded app has the expected structure
49             docker_image: when docker_image is set to a docker image name, docker.sh will be generated on server/client/admin
50         """
51         self.enable_byoc = enable_byoc
52         self.config_folder = config_folder
53         self.docker_image = docker_image
54         self.app_validator = app_validator
55         self.overseer_agent = overseer_agent
56         self.snapshot_persistor = snapshot_persistor
57 
58     def _write(self, file_full_path, content, mode, exe=False):
59         mode = mode + "w"
60         with open(file_full_path, mode) as f:
61             f.write(content)
62         if exe:
63             os.chmod(file_full_path, 0o755)
64 
65     def _build_overseer(self, overseer, ctx):
66         dest_dir = self.get_kit_dir(overseer, ctx)
67         self._write(
68             os.path.join(dest_dir, "start.sh"),
69             self.template["start_svr_sh"],
70             "t",
71             exe=True,
72         )
73         protocol = overseer.props.get("protocol", "http")
74         api_root = overseer.props.get("api_root", "/api/v1/")
75         default_port = "443" if protocol == "https" else "80"
76         port = overseer.props.get("port", default_port)
77         replacement_dict = {"port": port}
78         admins = self.study.get_participants_by_type("admin", first_only=False)
79         privilege_dict = dict()
80         for admin in admins:
81             for role in admin.props.get("roles", {}):
82                 if role in privilege_dict:
83                     privilege_dict[role].append(admin.subject)
84                 else:
85                     privilege_dict[role] = [admin.subject]
86         self._write(
87             os.path.join(dest_dir, "privilege.yml"),
88             yaml.dump(privilege_dict, Dumper=yaml.Dumper),
89             "t",
90             exe=False,
91         )
92 
93         if self.docker_image:
94             self._write(
95                 os.path.join(dest_dir, "docker.sh"),
96                 sh_replace(self.template["docker_svr_sh"], replacement_dict),
97                 "t",
98                 exe=True,
99             )
100         self._write(
101             os.path.join(dest_dir, "gunicorn.conf.py"),
102             sh_replace(self.template["gunicorn_conf_py"], replacement_dict),
103             "t",
104             exe=False,
105         )
106         self._write(
107             os.path.join(dest_dir, "start.sh"),
108             self.template["start_ovsr_sh"],
109             "t",
110             exe=True,
111         )
112         if port:
113             ctx["overseer_end_point"] = f"{protocol}://{overseer.name}:{port}{api_root}"
114         else:
115             ctx["overseer_end_point"] = f"{protocol}://{overseer.name}{api_root}"
116 
117     def _build_server(self, server, ctx):
118         config = json.loads(self.template["fed_server"])
119         dest_dir = self.get_kit_dir(server, ctx)
120         server_0 = config["servers"][0]
121         server_0["name"] = self.study_name
122         admin_port = server.props.get("admin_port", 8003)
123         ctx["admin_port"] = admin_port
124         fed_learn_port = server.props.get("fed_learn_port", 8002)
125         ctx["fed_learn_port"] = fed_learn_port
126         ctx["server_name"] = server.name
127         server_0["service"]["target"] = f"{server.name}:{fed_learn_port}"
128         server_0["admin_host"] = server.name
129         server_0["admin_port"] = admin_port
130         config["enable_byoc"] = server.enable_byoc
131         if self.app_validator:
132             config["app_validator"] = {"path": self.app_validator}
133         if self.overseer_agent:
134             overseer_agent = copy.deepcopy(self.overseer_agent)
135             if overseer_agent.get("overseer_exists", True):
136                 overseer_agent["args"] = {
137                     "role": "server",
138                     "overseer_end_point": ctx.get("overseer_end_point", ""),
139                     "project": self.study_name,
140                     "name": server.name,
141                     "fl_port": str(fed_learn_port),
142                     "admin_port": str(admin_port),
143                 }
144             overseer_agent.pop("overseer_exists", None)
145             config["overseer_agent"] = overseer_agent
146         if self.snapshot_persistor:
147             config["snapshot_persistor"] = self.snapshot_persistor
148         self._write(os.path.join(dest_dir, "fed_server.json"), json.dumps(config), "t")
149         replacement_dict = {
150             "admin_port": admin_port,
151             "fed_learn_port": fed_learn_port,
152             "config_folder": self.config_folder,
153             "docker_image": self.docker_image,
154         }
155         if self.docker_image:
156             self._write(
157                 os.path.join(dest_dir, "docker.sh"),
158                 sh_replace(self.template["docker_svr_sh"], replacement_dict),
159                 "t",
160                 exe=True,
161             )
162         self._write(
163             os.path.join(dest_dir, "start.sh"),
164             self.template["start_svr_sh"],
165             "t",
166             exe=True,
167         )
168         self._write(
169             os.path.join(dest_dir, "sub_start.sh"),
170             sh_replace(self.template["sub_start_svr_sh"], replacement_dict),
171             "t",
172             exe=True,
173         )
174         self._write(
175             os.path.join(dest_dir, "log.config"),
176             self.template["log_config"],
177             "t",
178         )
179         self._write(
180             os.path.join(dest_dir, "readme.txt"),
181             self.template["readme_fs"],
182             "t",
183         )
184         self._write(
185             os.path.join(dest_dir, "stop_fl.sh"),
186             self.template["stop_fl_sh"],
187             "t",
188             exe=True,
189         )
190 
191     def _build_client(self, client, ctx):
192         config = json.loads(self.template["fed_client"])
193         dest_dir = self.get_kit_dir(client, ctx)
194         fed_learn_port = ctx.get("fed_learn_port")
195         server_name = ctx.get("server_name")
196         # config["servers"][0]["service"]["target"] = f"{server_name}:{fed_learn_port}"
197         config["servers"][0]["name"] = self.study_name
198         config["enable_byoc"] = client.enable_byoc
199         replacement_dict = {
200             "client_name": f"{client.subject}",
201             "config_folder": self.config_folder,
202             "docker_image": self.docker_image,
203         }
204         if self.overseer_agent:
205             overseer_agent = copy.deepcopy(self.overseer_agent)
206             if overseer_agent.get("overseer_exists", True):
207                 overseer_agent["args"] = {
208                     "role": "client",
209                     "overseer_end_point": ctx.get("overseer_end_point", ""),
210                     "project": self.study_name,
211                     "name": client.subject,
212                 }
213             overseer_agent.pop("overseer_exists", None)
214             config["overseer_agent"] = overseer_agent
215 
216         self._write(os.path.join(dest_dir, "fed_client.json"), json.dumps(config), "t")
217         if self.docker_image:
218             self._write(
219                 os.path.join(dest_dir, "docker.sh"),
220                 sh_replace(self.template["docker_cln_sh"], replacement_dict),
221                 "t",
222                 exe=True,
223             )
224         self._write(
225             os.path.join(dest_dir, "start.sh"),
226             self.template["start_cln_sh"],
227             "t",
228             exe=True,
229         )
230         self._write(
231             os.path.join(dest_dir, "sub_start.sh"),
232             sh_replace(self.template["sub_start_cln_sh"], replacement_dict),
233             "t",
234             exe=True,
235         )
236         self._write(
237             os.path.join(dest_dir, "log.config"),
238             self.template["log_config"],
239             "t",
240         )
241         self._write(
242             os.path.join(dest_dir, "readme.txt"),
243             self.template["readme_fc"],
244             "t",
245         )
246         self._write(
247             os.path.join(dest_dir, "stop_fl.sh"),
248             self.template["stop_fl_sh"],
249             "t",
250             exe=True,
251         )
252 
253     def _build_admin(self, admin, ctx):
254         config = json.loads(self.template["fed_admin"])
255         dest_dir = self.get_kit_dir(admin, ctx)
256         admin_port = ctx.get("admin_port")
257         server_name = ctx.get("server_name")
258 
259         replacement_dict = {
260             "cn": f"{server_name}",
261             "admin_port": f"{admin_port}",
262             "docker_image": self.docker_image,
263         }
264         agent_config = dict()
265         if self.overseer_agent:
266             overseer_agent = copy.deepcopy(self.overseer_agent)
267             if overseer_agent.get("overseer_exists", True):
268                 overseer_agent["args"] = {
269                     "role": "admin",
270                     "overseer_end_point": ctx.get("overseer_end_point", ""),
271                     "project": self.study_name,
272                     "name": admin.subject,
273                 }
274             overseer_agent.pop("overseer_exists", None)
275             agent_config["overseer_agent"] = overseer_agent
276         config["admin"].update(agent_config)
277         self._write(os.path.join(dest_dir, "fed_admin.json"), json.dumps(config), "t")
278         if self.docker_image:
279             self._write(
280                 os.path.join(dest_dir, "docker.sh"),
281                 sh_replace(self.template["docker_adm_sh"], replacement_dict),
282                 "t",
283                 exe=True,
284             )
285         self._write(
286             os.path.join(dest_dir, "fl_admin.sh"),
287             sh_replace(self.template["fl_admin_sh"], replacement_dict),
288             "t",
289             exe=True,
290         )
291         self._write(
292             os.path.join(dest_dir, "readme.txt"),
293             self.template["readme_am"],
294             "t",
295         )
296 
297     def build(self, study, ctx):
298         self.template = ctx.get("template")
299         self.study_name = study.name
300         self.study = study
301         overseer = study.get_participants_by_type("overseer")
302         self._build_overseer(overseer, ctx)
303         servers = study.get_participants_by_type("server", first_only=False)
304         for server in servers:
305             self._build_server(server, ctx)
306 
307         for client in study.get_participants_by_type("client", first_only=False):
308             self._build_client(client, ctx)
309 
310         for admin in study.get_participants_by_type("admin", first_only=False):
311             self._build_admin(admin, ctx)
312
```
--- 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/nvflare/lighter/impl/static_file.py b/nvflare/lighter/impl/static_file.py
--- a/nvflare/lighter/impl/static_file.py
+++ b/nvflare/lighter/impl/static_file.py
@@ -145,7 +145,7 @@
             config["overseer_agent"] = overseer_agent
         if self.snapshot_persistor:
             config["snapshot_persistor"] = self.snapshot_persistor
-        self._write(os.path.join(dest_dir, "fed_server.json"), json.dumps(config), "t")
+        self._write(os.path.join(dest_dir, "fed_server.json"), json.dumps(config, sort_keys=True, indent=2), "t")
         replacement_dict = {
             "admin_port": admin_port,
             "fed_learn_port": fed_learn_port,
@@ -213,7 +213,7 @@
             overseer_agent.pop("overseer_exists", None)
             config["overseer_agent"] = overseer_agent
 
-        self._write(os.path.join(dest_dir, "fed_client.json"), json.dumps(config), "t")
+        self._write(os.path.join(dest_dir, "fed_client.json"), json.dumps(config, sort_keys=True, indent=2), "t")
         if self.docker_image:
             self._write(
                 os.path.join(dest_dir, "docker.sh"),
@@ -274,7 +274,7 @@
             overseer_agent.pop("overseer_exists", None)
             agent_config["overseer_agent"] = overseer_agent
         config["admin"].update(agent_config)
-        self._write(os.path.join(dest_dir, "fed_admin.json"), json.dumps(config), "t")
+        self._write(os.path.join(dest_dir, "fed_admin.json"), json.dumps(config, sort_keys=True, indent=2), "t")
         if self.docker_image:
             self._write(
                 os.path.join(dest_dir, "docker.sh"),

{"golden_diff": "diff --git a/nvflare/lighter/impl/static_file.py b/nvflare/lighter/impl/static_file.py\n--- a/nvflare/lighter/impl/static_file.py\n+++ b/nvflare/lighter/impl/static_file.py\n@@ -145,7 +145,7 @@\n             config[\"overseer_agent\"] = overseer_agent\n         if self.snapshot_persistor:\n             config[\"snapshot_persistor\"] = self.snapshot_persistor\n-        self._write(os.path.join(dest_dir, \"fed_server.json\"), json.dumps(config), \"t\")\n+        self._write(os.path.join(dest_dir, \"fed_server.json\"), json.dumps(config, sort_keys=True, indent=2), \"t\")\n         replacement_dict = {\n             \"admin_port\": admin_port,\n             \"fed_learn_port\": fed_learn_port,\n@@ -213,7 +213,7 @@\n             overseer_agent.pop(\"overseer_exists\", None)\n             config[\"overseer_agent\"] = overseer_agent\n \n-        self._write(os.path.join(dest_dir, \"fed_client.json\"), json.dumps(config), \"t\")\n+        self._write(os.path.join(dest_dir, \"fed_client.json\"), json.dumps(config, sort_keys=True, indent=2), \"t\")\n         if self.docker_image:\n             self._write(\n                 os.path.join(dest_dir, \"docker.sh\"),\n@@ -274,7 +274,7 @@\n             overseer_agent.pop(\"overseer_exists\", None)\n             agent_config[\"overseer_agent\"] = overseer_agent\n         config[\"admin\"].update(agent_config)\n-        self._write(os.path.join(dest_dir, \"fed_admin.json\"), json.dumps(config), \"t\")\n+        self._write(os.path.join(dest_dir, \"fed_admin.json\"), json.dumps(config, sort_keys=True, indent=2), \"t\")\n         if self.docker_image:\n             self._write(\n                 os.path.join(dest_dir, \"docker.sh\"),\n", "issue": "json files created by provision are not human readable\n\n", "before_files": [{"content": "# Copyright (c) 2021-2022, NVIDIA CORPORATION.  All rights reserved.\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 copy\nimport json\nimport os\n\nimport yaml\n\nfrom nvflare.lighter.spec import Builder\nfrom nvflare.lighter.utils import sh_replace\n\n\nclass StaticFileBuilder(Builder):\n    def __init__(\n        self,\n        enable_byoc=False,\n        config_folder=\"\",\n        app_validator=\"\",\n        docker_image=\"\",\n        snapshot_persistor=\"\",\n        overseer_agent=\"\",\n    ):\n        \"\"\"Build all static files from template.\n\n        Uses the information from project.yml through study to go through the participants and write the contents of\n        each file with the template, and replacing with the appropriate values from project.yml.\n\n        Usually, two main categories of files are created in all FL participants, static and dynamic. Static files\n        have similar contents among different participants, with small differences.  For example, the differences in\n        sub_start.sh are client name and python module.  Those are basically static files.  This builder uses template\n        file and string replacement to generate those static files for each participant.\n\n        Args:\n            enable_byoc: for each participant, true to enable loading of code in the custom folder of applications\n            config_folder: usually \"config\"\n            app_validator: optional path to an app validator to verify that uploaded app has the expected structure\n            docker_image: when docker_image is set to a docker image name, docker.sh will be generated on server/client/admin\n        \"\"\"\n        self.enable_byoc = enable_byoc\n        self.config_folder = config_folder\n        self.docker_image = docker_image\n        self.app_validator = app_validator\n        self.overseer_agent = overseer_agent\n        self.snapshot_persistor = snapshot_persistor\n\n    def _write(self, file_full_path, content, mode, exe=False):\n        mode = mode + \"w\"\n        with open(file_full_path, mode) as f:\n            f.write(content)\n        if exe:\n            os.chmod(file_full_path, 0o755)\n\n    def _build_overseer(self, overseer, ctx):\n        dest_dir = self.get_kit_dir(overseer, ctx)\n        self._write(\n            os.path.join(dest_dir, \"start.sh\"),\n            self.template[\"start_svr_sh\"],\n            \"t\",\n            exe=True,\n        )\n        protocol = overseer.props.get(\"protocol\", \"http\")\n        api_root = overseer.props.get(\"api_root\", \"/api/v1/\")\n        default_port = \"443\" if protocol == \"https\" else \"80\"\n        port = overseer.props.get(\"port\", default_port)\n        replacement_dict = {\"port\": port}\n        admins = self.study.get_participants_by_type(\"admin\", first_only=False)\n        privilege_dict = dict()\n        for admin in admins:\n            for role in admin.props.get(\"roles\", {}):\n                if role in privilege_dict:\n                    privilege_dict[role].append(admin.subject)\n                else:\n                    privilege_dict[role] = [admin.subject]\n        self._write(\n            os.path.join(dest_dir, \"privilege.yml\"),\n            yaml.dump(privilege_dict, Dumper=yaml.Dumper),\n            \"t\",\n            exe=False,\n        )\n\n        if self.docker_image:\n            self._write(\n                os.path.join(dest_dir, \"docker.sh\"),\n                sh_replace(self.template[\"docker_svr_sh\"], replacement_dict),\n                \"t\",\n                exe=True,\n            )\n        self._write(\n            os.path.join(dest_dir, \"gunicorn.conf.py\"),\n            sh_replace(self.template[\"gunicorn_conf_py\"], replacement_dict),\n            \"t\",\n            exe=False,\n        )\n        self._write(\n            os.path.join(dest_dir, \"start.sh\"),\n            self.template[\"start_ovsr_sh\"],\n            \"t\",\n            exe=True,\n        )\n        if port:\n            ctx[\"overseer_end_point\"] = f\"{protocol}://{overseer.name}:{port}{api_root}\"\n        else:\n            ctx[\"overseer_end_point\"] = f\"{protocol}://{overseer.name}{api_root}\"\n\n    def _build_server(self, server, ctx):\n        config = json.loads(self.template[\"fed_server\"])\n        dest_dir = self.get_kit_dir(server, ctx)\n        server_0 = config[\"servers\"][0]\n        server_0[\"name\"] = self.study_name\n        admin_port = server.props.get(\"admin_port\", 8003)\n        ctx[\"admin_port\"] = admin_port\n        fed_learn_port = server.props.get(\"fed_learn_port\", 8002)\n        ctx[\"fed_learn_port\"] = fed_learn_port\n        ctx[\"server_name\"] = server.name\n        server_0[\"service\"][\"target\"] = f\"{server.name}:{fed_learn_port}\"\n        server_0[\"admin_host\"] = server.name\n        server_0[\"admin_port\"] = admin_port\n        config[\"enable_byoc\"] = server.enable_byoc\n        if self.app_validator:\n            config[\"app_validator\"] = {\"path\": self.app_validator}\n        if self.overseer_agent:\n            overseer_agent = copy.deepcopy(self.overseer_agent)\n            if overseer_agent.get(\"overseer_exists\", True):\n                overseer_agent[\"args\"] = {\n                    \"role\": \"server\",\n                    \"overseer_end_point\": ctx.get(\"overseer_end_point\", \"\"),\n                    \"project\": self.study_name,\n                    \"name\": server.name,\n                    \"fl_port\": str(fed_learn_port),\n                    \"admin_port\": str(admin_port),\n                }\n            overseer_agent.pop(\"overseer_exists\", None)\n            config[\"overseer_agent\"] = overseer_agent\n        if self.snapshot_persistor:\n            config[\"snapshot_persistor\"] = self.snapshot_persistor\n        self._write(os.path.join(dest_dir, \"fed_server.json\"), json.dumps(config), \"t\")\n        replacement_dict = {\n            \"admin_port\": admin_port,\n            \"fed_learn_port\": fed_learn_port,\n            \"config_folder\": self.config_folder,\n            \"docker_image\": self.docker_image,\n        }\n        if self.docker_image:\n            self._write(\n                os.path.join(dest_dir, \"docker.sh\"),\n                sh_replace(self.template[\"docker_svr_sh\"], replacement_dict),\n                \"t\",\n                exe=True,\n            )\n        self._write(\n            os.path.join(dest_dir, \"start.sh\"),\n            self.template[\"start_svr_sh\"],\n            \"t\",\n            exe=True,\n        )\n        self._write(\n            os.path.join(dest_dir, \"sub_start.sh\"),\n            sh_replace(self.template[\"sub_start_svr_sh\"], replacement_dict),\n            \"t\",\n            exe=True,\n        )\n        self._write(\n            os.path.join(dest_dir, \"log.config\"),\n            self.template[\"log_config\"],\n            \"t\",\n        )\n        self._write(\n            os.path.join(dest_dir, \"readme.txt\"),\n            self.template[\"readme_fs\"],\n            \"t\",\n        )\n        self._write(\n            os.path.join(dest_dir, \"stop_fl.sh\"),\n            self.template[\"stop_fl_sh\"],\n            \"t\",\n            exe=True,\n        )\n\n    def _build_client(self, client, ctx):\n        config = json.loads(self.template[\"fed_client\"])\n        dest_dir = self.get_kit_dir(client, ctx)\n        fed_learn_port = ctx.get(\"fed_learn_port\")\n        server_name = ctx.get(\"server_name\")\n        # config[\"servers\"][0][\"service\"][\"target\"] = f\"{server_name}:{fed_learn_port}\"\n        config[\"servers\"][0][\"name\"] = self.study_name\n        config[\"enable_byoc\"] = client.enable_byoc\n        replacement_dict = {\n            \"client_name\": f\"{client.subject}\",\n            \"config_folder\": self.config_folder,\n            \"docker_image\": self.docker_image,\n        }\n        if self.overseer_agent:\n            overseer_agent = copy.deepcopy(self.overseer_agent)\n            if overseer_agent.get(\"overseer_exists\", True):\n                overseer_agent[\"args\"] = {\n                    \"role\": \"client\",\n                    \"overseer_end_point\": ctx.get(\"overseer_end_point\", \"\"),\n                    \"project\": self.study_name,\n                    \"name\": client.subject,\n                }\n            overseer_agent.pop(\"overseer_exists\", None)\n            config[\"overseer_agent\"] = overseer_agent\n\n        self._write(os.path.join(dest_dir, \"fed_client.json\"), json.dumps(config), \"t\")\n        if self.docker_image:\n            self._write(\n                os.path.join(dest_dir, \"docker.sh\"),\n                sh_replace(self.template[\"docker_cln_sh\"], replacement_dict),\n                \"t\",\n                exe=True,\n            )\n        self._write(\n            os.path.join(dest_dir, \"start.sh\"),\n            self.template[\"start_cln_sh\"],\n            \"t\",\n            exe=True,\n        )\n        self._write(\n            os.path.join(dest_dir, \"sub_start.sh\"),\n            sh_replace(self.template[\"sub_start_cln_sh\"], replacement_dict),\n            \"t\",\n            exe=True,\n        )\n        self._write(\n            os.path.join(dest_dir, \"log.config\"),\n            self.template[\"log_config\"],\n            \"t\",\n        )\n        self._write(\n            os.path.join(dest_dir, \"readme.txt\"),\n            self.template[\"readme_fc\"],\n            \"t\",\n        )\n        self._write(\n            os.path.join(dest_dir, \"stop_fl.sh\"),\n            self.template[\"stop_fl_sh\"],\n            \"t\",\n            exe=True,\n        )\n\n    def _build_admin(self, admin, ctx):\n        config = json.loads(self.template[\"fed_admin\"])\n        dest_dir = self.get_kit_dir(admin, ctx)\n        admin_port = ctx.get(\"admin_port\")\n        server_name = ctx.get(\"server_name\")\n\n        replacement_dict = {\n            \"cn\": f\"{server_name}\",\n            \"admin_port\": f\"{admin_port}\",\n            \"docker_image\": self.docker_image,\n        }\n        agent_config = dict()\n        if self.overseer_agent:\n            overseer_agent = copy.deepcopy(self.overseer_agent)\n            if overseer_agent.get(\"overseer_exists\", True):\n                overseer_agent[\"args\"] = {\n                    \"role\": \"admin\",\n                    \"overseer_end_point\": ctx.get(\"overseer_end_point\", \"\"),\n                    \"project\": self.study_name,\n                    \"name\": admin.subject,\n                }\n            overseer_agent.pop(\"overseer_exists\", None)\n            agent_config[\"overseer_agent\"] = overseer_agent\n        config[\"admin\"].update(agent_config)\n        self._write(os.path.join(dest_dir, \"fed_admin.json\"), json.dumps(config), \"t\")\n        if self.docker_image:\n            self._write(\n                os.path.join(dest_dir, \"docker.sh\"),\n                sh_replace(self.template[\"docker_adm_sh\"], replacement_dict),\n                \"t\",\n                exe=True,\n            )\n        self._write(\n            os.path.join(dest_dir, \"fl_admin.sh\"),\n            sh_replace(self.template[\"fl_admin_sh\"], replacement_dict),\n            \"t\",\n            exe=True,\n        )\n        self._write(\n            os.path.join(dest_dir, \"readme.txt\"),\n            self.template[\"readme_am\"],\n            \"t\",\n        )\n\n    def build(self, study, ctx):\n        self.template = ctx.get(\"template\")\n        self.study_name = study.name\n        self.study = study\n        overseer = study.get_participants_by_type(\"overseer\")\n        self._build_overseer(overseer, ctx)\n        servers = study.get_participants_by_type(\"server\", first_only=False)\n        for server in servers:\n            self._build_server(server, ctx)\n\n        for client in study.get_participants_by_type(\"client\", first_only=False):\n            self._build_client(client, ctx)\n\n        for admin in study.get_participants_by_type(\"admin\", first_only=False):\n            self._build_admin(admin, ctx)\n", "path": "nvflare/lighter/impl/static_file.py"}], "after_files": [{"content": "# Copyright (c) 2021-2022, NVIDIA CORPORATION.  All rights reserved.\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 copy\nimport json\nimport os\n\nimport yaml\n\nfrom nvflare.lighter.spec import Builder\nfrom nvflare.lighter.utils import sh_replace\n\n\nclass StaticFileBuilder(Builder):\n    def __init__(\n        self,\n        enable_byoc=False,\n        config_folder=\"\",\n        app_validator=\"\",\n        docker_image=\"\",\n        snapshot_persistor=\"\",\n        overseer_agent=\"\",\n    ):\n        \"\"\"Build all static files from template.\n\n        Uses the information from project.yml through study to go through the participants and write the contents of\n        each file with the template, and replacing with the appropriate values from project.yml.\n\n        Usually, two main categories of files are created in all FL participants, static and dynamic. Static files\n        have similar contents among different participants, with small differences.  For example, the differences in\n        sub_start.sh are client name and python module.  Those are basically static files.  This builder uses template\n        file and string replacement to generate those static files for each participant.\n\n        Args:\n            enable_byoc: for each participant, true to enable loading of code in the custom folder of applications\n            config_folder: usually \"config\"\n            app_validator: optional path to an app validator to verify that uploaded app has the expected structure\n            docker_image: when docker_image is set to a docker image name, docker.sh will be generated on server/client/admin\n        \"\"\"\n        self.enable_byoc = enable_byoc\n        self.config_folder = config_folder\n        self.docker_image = docker_image\n        self.app_validator = app_validator\n        self.overseer_agent = overseer_agent\n        self.snapshot_persistor = snapshot_persistor\n\n    def _write(self, file_full_path, content, mode, exe=False):\n        mode = mode + \"w\"\n        with open(file_full_path, mode) as f:\n            f.write(content)\n        if exe:\n            os.chmod(file_full_path, 0o755)\n\n    def _build_overseer(self, overseer, ctx):\n        dest_dir = self.get_kit_dir(overseer, ctx)\n        self._write(\n            os.path.join(dest_dir, \"start.sh\"),\n            self.template[\"start_svr_sh\"],\n            \"t\",\n            exe=True,\n        )\n        protocol = overseer.props.get(\"protocol\", \"http\")\n        api_root = overseer.props.get(\"api_root\", \"/api/v1/\")\n        default_port = \"443\" if protocol == \"https\" else \"80\"\n        port = overseer.props.get(\"port\", default_port)\n        replacement_dict = {\"port\": port}\n        admins = self.study.get_participants_by_type(\"admin\", first_only=False)\n        privilege_dict = dict()\n        for admin in admins:\n            for role in admin.props.get(\"roles\", {}):\n                if role in privilege_dict:\n                    privilege_dict[role].append(admin.subject)\n                else:\n                    privilege_dict[role] = [admin.subject]\n        self._write(\n            os.path.join(dest_dir, \"privilege.yml\"),\n            yaml.dump(privilege_dict, Dumper=yaml.Dumper),\n            \"t\",\n            exe=False,\n        )\n\n        if self.docker_image:\n            self._write(\n                os.path.join(dest_dir, \"docker.sh\"),\n                sh_replace(self.template[\"docker_svr_sh\"], replacement_dict),\n                \"t\",\n                exe=True,\n            )\n        self._write(\n            os.path.join(dest_dir, \"gunicorn.conf.py\"),\n            sh_replace(self.template[\"gunicorn_conf_py\"], replacement_dict),\n            \"t\",\n            exe=False,\n        )\n        self._write(\n            os.path.join(dest_dir, \"start.sh\"),\n            self.template[\"start_ovsr_sh\"],\n            \"t\",\n            exe=True,\n        )\n        if port:\n            ctx[\"overseer_end_point\"] = f\"{protocol}://{overseer.name}:{port}{api_root}\"\n        else:\n            ctx[\"overseer_end_point\"] = f\"{protocol}://{overseer.name}{api_root}\"\n\n    def _build_server(self, server, ctx):\n        config = json.loads(self.template[\"fed_server\"])\n        dest_dir = self.get_kit_dir(server, ctx)\n        server_0 = config[\"servers\"][0]\n        server_0[\"name\"] = self.study_name\n        admin_port = server.props.get(\"admin_port\", 8003)\n        ctx[\"admin_port\"] = admin_port\n        fed_learn_port = server.props.get(\"fed_learn_port\", 8002)\n        ctx[\"fed_learn_port\"] = fed_learn_port\n        ctx[\"server_name\"] = server.name\n        server_0[\"service\"][\"target\"] = f\"{server.name}:{fed_learn_port}\"\n        server_0[\"admin_host\"] = server.name\n        server_0[\"admin_port\"] = admin_port\n        config[\"enable_byoc\"] = server.enable_byoc\n        if self.app_validator:\n            config[\"app_validator\"] = {\"path\": self.app_validator}\n        if self.overseer_agent:\n            overseer_agent = copy.deepcopy(self.overseer_agent)\n            if overseer_agent.get(\"overseer_exists\", True):\n                overseer_agent[\"args\"] = {\n                    \"role\": \"server\",\n                    \"overseer_end_point\": ctx.get(\"overseer_end_point\", \"\"),\n                    \"project\": self.study_name,\n                    \"name\": server.name,\n                    \"fl_port\": str(fed_learn_port),\n                    \"admin_port\": str(admin_port),\n                }\n            overseer_agent.pop(\"overseer_exists\", None)\n            config[\"overseer_agent\"] = overseer_agent\n        if self.snapshot_persistor:\n            config[\"snapshot_persistor\"] = self.snapshot_persistor\n        self._write(os.path.join(dest_dir, \"fed_server.json\"), json.dumps(config, sort_keys=True, indent=2), \"t\")\n        replacement_dict = {\n            \"admin_port\": admin_port,\n            \"fed_learn_port\": fed_learn_port,\n            \"config_folder\": self.config_folder,\n            \"docker_image\": self.docker_image,\n        }\n        if self.docker_image:\n            self._write(\n                os.path.join(dest_dir, \"docker.sh\"),\n                sh_replace(self.template[\"docker_svr_sh\"], replacement_dict),\n                \"t\",\n                exe=True,\n            )\n        self._write(\n            os.path.join(dest_dir, \"start.sh\"),\n            self.template[\"start_svr_sh\"],\n            \"t\",\n            exe=True,\n        )\n        self._write(\n            os.path.join(dest_dir, \"sub_start.sh\"),\n            sh_replace(self.template[\"sub_start_svr_sh\"], replacement_dict),\n            \"t\",\n            exe=True,\n        )\n        self._write(\n            os.path.join(dest_dir, \"log.config\"),\n            self.template[\"log_config\"],\n            \"t\",\n        )\n        self._write(\n            os.path.join(dest_dir, \"readme.txt\"),\n            self.template[\"readme_fs\"],\n            \"t\",\n        )\n        self._write(\n            os.path.join(dest_dir, \"stop_fl.sh\"),\n            self.template[\"stop_fl_sh\"],\n            \"t\",\n            exe=True,\n        )\n\n    def _build_client(self, client, ctx):\n        config = json.loads(self.template[\"fed_client\"])\n        dest_dir = self.get_kit_dir(client, ctx)\n        fed_learn_port = ctx.get(\"fed_learn_port\")\n        server_name = ctx.get(\"server_name\")\n        # config[\"servers\"][0][\"service\"][\"target\"] = f\"{server_name}:{fed_learn_port}\"\n        config[\"servers\"][0][\"name\"] = self.study_name\n        config[\"enable_byoc\"] = client.enable_byoc\n        replacement_dict = {\n            \"client_name\": f\"{client.subject}\",\n            \"config_folder\": self.config_folder,\n            \"docker_image\": self.docker_image,\n        }\n        if self.overseer_agent:\n            overseer_agent = copy.deepcopy(self.overseer_agent)\n            if overseer_agent.get(\"overseer_exists\", True):\n                overseer_agent[\"args\"] = {\n                    \"role\": \"client\",\n                    \"overseer_end_point\": ctx.get(\"overseer_end_point\", \"\"),\n                    \"project\": self.study_name,\n                    \"name\": client.subject,\n                }\n            overseer_agent.pop(\"overseer_exists\", None)\n            config[\"overseer_agent\"] = overseer_agent\n\n        self._write(os.path.join(dest_dir, \"fed_client.json\"), json.dumps(config, sort_keys=True, indent=2), \"t\")\n        if self.docker_image:\n            self._write(\n                os.path.join(dest_dir, \"docker.sh\"),\n                sh_replace(self.template[\"docker_cln_sh\"], replacement_dict),\n                \"t\",\n                exe=True,\n            )\n        self._write(\n            os.path.join(dest_dir, \"start.sh\"),\n            self.template[\"start_cln_sh\"],\n            \"t\",\n            exe=True,\n        )\n        self._write(\n            os.path.join(dest_dir, \"sub_start.sh\"),\n            sh_replace(self.template[\"sub_start_cln_sh\"], replacement_dict),\n            \"t\",\n            exe=True,\n        )\n        self._write(\n            os.path.join(dest_dir, \"log.config\"),\n            self.template[\"log_config\"],\n            \"t\",\n        )\n        self._write(\n            os.path.join(dest_dir, \"readme.txt\"),\n            self.template[\"readme_fc\"],\n            \"t\",\n        )\n        self._write(\n            os.path.join(dest_dir, \"stop_fl.sh\"),\n            self.template[\"stop_fl_sh\"],\n            \"t\",\n            exe=True,\n        )\n\n    def _build_admin(self, admin, ctx):\n        config = json.loads(self.template[\"fed_admin\"])\n        dest_dir = self.get_kit_dir(admin, ctx)\n        admin_port = ctx.get(\"admin_port\")\n        server_name = ctx.get(\"server_name\")\n\n        replacement_dict = {\n            \"cn\": f\"{server_name}\",\n            \"admin_port\": f\"{admin_port}\",\n            \"docker_image\": self.docker_image,\n        }\n        agent_config = dict()\n        if self.overseer_agent:\n            overseer_agent = copy.deepcopy(self.overseer_agent)\n            if overseer_agent.get(\"overseer_exists\", True):\n                overseer_agent[\"args\"] = {\n                    \"role\": \"admin\",\n                    \"overseer_end_point\": ctx.get(\"overseer_end_point\", \"\"),\n                    \"project\": self.study_name,\n                    \"name\": admin.subject,\n                }\n            overseer_agent.pop(\"overseer_exists\", None)\n            agent_config[\"overseer_agent\"] = overseer_agent\n        config[\"admin\"].update(agent_config)\n        self._write(os.path.join(dest_dir, \"fed_admin.json\"), json.dumps(config, sort_keys=True, indent=2), \"t\")\n        if self.docker_image:\n            self._write(\n                os.path.join(dest_dir, \"docker.sh\"),\n                sh_replace(self.template[\"docker_adm_sh\"], replacement_dict),\n                \"t\",\n                exe=True,\n            )\n        self._write(\n            os.path.join(dest_dir, \"fl_admin.sh\"),\n            sh_replace(self.template[\"fl_admin_sh\"], replacement_dict),\n            \"t\",\n            exe=True,\n        )\n        self._write(\n            os.path.join(dest_dir, \"readme.txt\"),\n            self.template[\"readme_am\"],\n            \"t\",\n        )\n\n    def build(self, study, ctx):\n        self.template = ctx.get(\"template\")\n        self.study_name = study.name\n        self.study = study\n        overseer = study.get_participants_by_type(\"overseer\")\n        self._build_overseer(overseer, ctx)\n        servers = study.get_participants_by_type(\"server\", first_only=False)\n        for server in servers:\n            self._build_server(server, ctx)\n\n        for client in study.get_participants_by_type(\"client\", first_only=False):\n            self._build_client(client, ctx)\n\n        for admin in study.get_participants_by_type(\"admin\", first_only=False):\n            self._build_admin(admin, ctx)\n", "path": "nvflare/lighter/impl/static_file.py"}]}