Skip to content

Commit 2af2217

Browse files
committed
CH-157 refactor, docs, enhancements
1 parent c5a64e9 commit 2af2217

13 files changed

Lines changed: 170 additions & 49 deletions

File tree

application-templates/django-ninja/README.md

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,29 @@ Frontend code is inside the *frontend* directory.
3434

3535
Frontend is by default generated as a React web application, but no constraint about this specific technology.
3636

37-
#### Call the backend apis
37+
See also [frontend/README.md]
38+
39+
#### Generate API client stubs
3840
All the api stubs are automatically generated in the [frontend/rest](frontend/rest) directory by `harness-application`
3941
and `harness-generate`.
4042

43+
To update frontend client stubs, run
44+
45+
```
46+
harness-generate clients __APP_NAME__ -t
47+
```
48+
49+
Stubs can also be updated using the `genapi.sh` from the api folder.
50+
4151
## Local build & run
4252

43-
### Install dependencies
53+
### Install Python dependencies
4454
1 - Clone cloud-harness into your project root folder
4555

4656
2 - Run the dev setup script
4757
```
4858
cd applications/__APP_NAME__
49-
bash dev-setup.sh
59+
source dev-setup.sh
5060
```
5161

5262
### Prepare backend
@@ -62,25 +72,43 @@ cd static/www
6272
ln -s ../../../frontend/dist dist
6373
```
6474

65-
### Build frontend
75+
### Run frontend
6676

67-
Compile the frontend
68-
```bash
69-
cd frontend
70-
npm install
71-
npm run build
72-
```
77+
- `yarn dev` Local dev with no backend (no or mock data, cookie required)
78+
- `yarn start` Local dev with backend on localhost:8000 -- see next paragraph (cookie required)
79+
- `yarn start:dev` Local dev with backend on the remote dev deployment (cookie required)
80+
- `yarn start:local` Local dev with backend on the local dev deployment on mnp.local (cookie required)
81+
82+
To obtain the login cookie, login in the application with the forwarded backend, copy the `kc-access` cookie and set it into localhost:9000
7383

7484
### Run backend application
7585

7686
start the Django server
87+
7788
```bash
78-
uvicorn --workers 2 --host 0.0.0.0 --port 8000 django_baseapp.asgi:application
89+
ACCOUNTS_ADMIN_PASSWORD=metacell ACCOUNTS_ADMIN_USERNAME=admin CH_CURRENT_APP_NAME=__APP_NAME__ CH_VALUES_PATH=../../../deployment/helm/values.yaml DJANGO_SETTINGS_MODULE=django_baseapp.settings KUBERNETES_SERVICE_HOST=a uvicorn --host 0.0.0.0 --port 8000 django_baseapp.asgi:application
7990
```
8091

92+
Before running this backend, have to:
93+
- Run `harness-deployment ... -n [NAMESPACE] -i __APP_NAME__` with the setup
94+
- port-forward keycloak and the database (see below)
8195

8296
### Running local with port forwardings to a kubernetes cluster
8397
When you create port forwards to microservices in your k8s cluster you want to forced your local backend server to initialize
8498
the AuthService and EventService services.
8599
This can be done by setting the `KUBERNETES_SERVICE_HOST` environment variable to a dummy or correct k8s service host.
86100
The `KUBERNETES_SERVICE_HOST` switch will activate the creation of the keycloak client and client roles of this microservice.
101+
102+
Run `port-forward.sh` to get the keycloak and database running.
103+
104+
To access those have to map to the hosts file:
105+
106+
```
107+
127.0.0.1 accounts.[NAMESPACE] __APP_NAME__-db
108+
```
109+
110+
After running the backend on port 8000, run `yarn start` to get a frontend to it
111+
112+
#### Vs code run configuration
113+
114+
Run configuration is automatically generated for VS code (__APP_NAME__ backend)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fuser -k 5432/tcp
2+
fuser -k 8080/tcp
3+
namespace=${1:-ch}
4+
echo "Port forwarding for $namespace"
5+
kubectl port-forward --namespace $namespace deployment/accounts 8080:8080 &
6+
kubectl port-forward --namespace $namespace deployment/__APP_NAME__-db 5432:5432 &

application-templates/webapp/frontend/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
"scripts": {
44
"dev": "vite",
55
"start": "DOMAIN=http://localhost:5000 vite",
6-
"start:dev": "DOMAIN=https://test.ch.metacell.us vite",
7-
"start:local": "DOMAIN=http://samples.ch vite",
6+
"start:dev": "DOMAIN=https://__APP_NAME__.ch.metacell.us vite",
7+
"start:local": "DOMAIN=http://__APP_NAME__.ch vite",
88
"prebuild": "eslint .",
99
"build": "vite build",
1010
"lint": "eslint src --report-unused-disable-directives --fix"
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
import { useState, useEffect } from 'react';
22

33

4-
import { TestApi } from '../rest/apis/TestApi'
4+
import { TestApi } from '../rest/__APP_NAME__/apis/TestApi'
55
const test = new TestApi();
66

77

88

99
const RestTest = () => {
1010
const [result, setResult] = useState<any>(null);
1111
useEffect(() => {
12-
test.ping().then((r) => setResult(r), () => setResult( "API error"));
12+
test.ping().then((r) => setResult(r), () => setResult("API error"));
1313
}, []);
14-
1514

16-
return result ? <p>Backend answered: { result } </p> : <p>Backend did not answer</p>
15+
16+
return result ? <p>Backend answered: {result} </p> : <p>Backend did not answer</p>
1717
}
1818

1919
export default RestTest;

infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
except:
5151
# no current app found, fall back to the default settings, there is a god change that
5252
# we are running on a developers local machine
53-
log.warning("Error setting current app configuration, continuing...")
53+
log.warning("Error setting current app configuration, was `harness-deployment` executed? Continuing...")
5454

5555
current_app = applications.ApplicationConfiguration({
5656
"name": app_name,

libraries/client/cloudharness_cli/cloudharness_cli/__init__.py

Whitespace-only changes.

libraries/client/cloudharness_cli/test/ninjatest/__init__.py

Whitespace-only changes.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# coding: utf-8
2+
3+
"""
4+
ninjatest API
5+
6+
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
7+
8+
The version of the OpenAPI document: 0.1.0
9+
Generated by OpenAPI Generator (https://openapi-generator.tech)
10+
11+
Do not edit the class manually.
12+
""" # noqa: E501
13+
14+
15+
import unittest
16+
17+
from cloudharness_cli.ninjatest.api.test_api import TestApi
18+
19+
20+
class TestTestApi(unittest.TestCase):
21+
"""TestApi unit test stubs"""
22+
23+
def setUp(self) -> None:
24+
self.api = TestApi()
25+
26+
def tearDown(self) -> None:
27+
pass
28+
29+
def test_ninjatest_api_live(self) -> None:
30+
"""Test case for ninjatest_api_live
31+
32+
Live
33+
"""
34+
pass
35+
36+
def test_ninjatest_api_ping(self) -> None:
37+
"""Test case for ninjatest_api_ping
38+
39+
Ping
40+
"""
41+
pass
42+
43+
def test_ninjatest_api_ready(self) -> None:
44+
"""Test case for ninjatest_api_ready
45+
46+
Ready
47+
"""
48+
pass
49+
50+
51+
if __name__ == '__main__':
52+
unittest.main()

tools/deployment-cli-tools/ch_cli_tools/application_builders.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def handle_post_merge(self):
8989
logging.info('Installing frontend dependencies')
9090
self.install_frontend_dependencies()
9191
logging.info('Generating ts client')
92-
generate_ts_client(self.api_path / 'openapi.yaml')
92+
generate_ts_client(self.api_path / 'openapi.yaml', self.app_name)
9393

9494
def create_vite_skaffold(self, frontend_path: pathlib.Path) -> None:
9595
self.run_command(

tools/deployment-cli-tools/ch_cli_tools/openapi.py

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from ch_cli_tools.manifest import get_manifest
1818

1919
from . import HERE
20-
from .utils import copymergedir, replaceindir, to_python_module
20+
from .utils import confirm, copymergedir, replace_in_file, replaceindir, to_python_module
2121

2222
CODEGEN = os.path.join(HERE, 'bin', 'openapi-generator-cli.jar')
2323
APPLICATIONS_SRC_PATH = os.path.join('applications')
@@ -129,33 +129,60 @@ def generate_python_client(module, openapi_file, client_src_path, lib_name=LIB_N
129129
os.system(command)
130130

131131

132-
def generate_ts_client(openapi_file):
132+
def generate_ts_client(openapi_file, app_name=""):
133133
get_dependencies()
134-
out_dir = f"{os.path.dirname(os.path.dirname(openapi_file))}/frontend/src/rest"
134+
out_dir = f"{os.path.dirname(os.path.dirname(openapi_file))}/frontend/src/rest/{app_name}"
135135
command = f"java -jar {CODEGEN} generate " \
136136
f"-i {openapi_file} " \
137137
f"-g typescript-fetch " \
138-
f"-o {out_dir}"
138+
f"-o {out_dir} "\
139+
f"--additional-properties=prefixParameterInterfaces=false"
139140
os.system(command)
140141

141142
replaceindir(out_dir, "http://localhost", '')
142143

143144

145+
def json2yaml(json_filename, yaml_file=None):
146+
import yaml
147+
if yaml_file is None:
148+
yaml_file = str(json_filename).replace('.json', '.yaml')
149+
with open(json_filename, 'r') as json_filename:
150+
data = json.load(json_filename)
151+
with open(yaml_file, 'w') as yaml_file:
152+
yaml.dump(data, yaml_file)
153+
154+
144155
def generate_openapi_from_ninja_schema(app_name: str, app_path: pathlib.Path) -> None:
145-
subprocess.check_call(["sh", "dev-setup.sh"], cwd=app_path)
146-
out_path = app_path / 'api' / 'openapi.yaml'
156+
# check if cloudharness_django python library is installed
157+
python_module = to_python_module(app_name)
158+
try:
159+
import cloudharness_django
160+
# dynamicall import python_module
161+
__import__(f'{python_module}')
162+
except ImportError:
163+
if confirm('Runtime env is not installed. Do you want to install it? [Y/n]'):
164+
subprocess.check_call(["sh", "dev-setup.sh"], cwd=app_path)
165+
else:
166+
logging.error('Runtime env is not installed. Cound not generate openapi files for Django Ninja.')
167+
return
168+
logging.info(f"Generating openapi files for Django Ninja for application {app_name}")
169+
out_path = app_path / 'api' / 'openapi.json'
147170

148171
manage_path = app_path / 'backend' / 'manage.py'
149172
command = [
150173
'python', manage_path, 'export_openapi_schema',
151174
'--settings', 'django_baseapp.settings',
152-
'--api', f'{to_python_module(app_name)}.api.api',
175+
'--api', f'{python_module}.api.api',
153176
'--output', out_path,
154177
'--indent', '2',
155178
]
156179

157180
subprocess.run(command)
158181

182+
replace_in_file(out_path, f'{app_name}_api_', '')
183+
184+
json2yaml(out_path)
185+
159186

160187
def get_dependencies():
161188
"""
@@ -235,6 +262,8 @@ def generate_clients(
235262
if not should_generate('client libraries'):
236263
return
237264

265+
logging.info('Generating client libraries for %s', str(client_types))
266+
238267
client_src_path = root_path / 'libraries' / 'client' / client_lib_name
239268
apps_path = root_path / 'applications'
240269
apps = (app for app in apps_path.iterdir() if app.is_dir())
@@ -253,7 +282,7 @@ def generate_clients(
253282
generate_python_client(manifest.app_name, openapi_file, client_src_path, lib_name=client_lib_name)
254283

255284
if TemplateType.WEBAPP in manifest.templates and ClientType.TS_CLIENT in client_types:
256-
generate_ts_client(openapi_file)
285+
generate_ts_client(openapi_file, app_name)
257286

258287
aggregate_packages(client_src_path, client_lib_name)
259288

0 commit comments

Comments
 (0)