Skip to content

Commit 0e3bc73

Browse files
feat: enable v1 root drf browsable
Signed-off-by: Alex <aizquier@redhat.com>
1 parent 07bae0c commit 0e3bc73

File tree

10 files changed

+192
-13
lines changed

10 files changed

+192
-13
lines changed

docs/deployment.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,5 @@ Minikube is the recommended method for macOS users
123123
**Note**: For fedora, the binary may be `go-task`.
124124

125125
You can now access the UI at <http://localhost:8080/eda/> using the above credentials.
126+
Also you can inspect the API documentation at <https://localhost:8443/api/eda/v1/docs>
127+
or navigate through the resources with the DRF browsable API at <https://localhost:8443/api/eda/v1/>

src/aap_eda/api/urls.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,22 +79,35 @@
7979
),
8080
]
8181

82-
v1_urls = [
83-
path("status/", core_views.StatusView.as_view()),
84-
path("", include(dab_urls)),
85-
path("", include(resource_api_urls)),
82+
eda_v1_urls = [
83+
path("status/", core_views.StatusView.as_view(), name="status"),
8684
path("", include(openapi_urls)),
87-
path("auth/session/login/", views.SessionLoginView.as_view()),
88-
path("auth/session/logout/", views.SessionLogoutView.as_view()),
85+
path(
86+
"auth/session/login/",
87+
views.SessionLoginView.as_view(),
88+
name="session-login",
89+
),
90+
path(
91+
"auth/session/logout/",
92+
views.SessionLogoutView.as_view(),
93+
name="session-logout",
94+
),
8995
path(
9096
"auth/token/refresh/",
9197
jwt_views.TokenRefreshView.as_view(),
92-
name="token_refresh",
98+
name="token-refresh",
9399
),
94-
path("users/me/", views.CurrentUserView.as_view()),
100+
path("users/me/", views.CurrentUserView.as_view(), name="current-user"),
95101
*router.urls,
96102
]
97103

104+
dab_urls = [
105+
path("", include(dab_urls)),
106+
path("", include(resource_api_urls)),
107+
]
108+
109+
v1_urls = eda_v1_urls + dab_urls
98110
urlpatterns = [
111+
path("v1/", views.ApiV1RootView.as_view()),
99112
path("v1/", include(v1_urls)),
100113
]

src/aap_eda/api/views/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from .event_stream import EventStreamViewSet
2121
from .organization import OrganizationViewSet
2222
from .project import ProjectViewSet
23+
from .root import ApiV1RootView
2324
from .rulebook import AuditRuleViewSet, RulebookViewSet
2425
from .team import TeamViewSet
2526
from .user import CurrentUserAwxTokenViewSet, CurrentUserView, UserViewSet
@@ -28,7 +29,6 @@
2829
# auth
2930
"SessionLoginView",
3031
"SessionLogoutView",
31-
"RoleViewSet",
3232
# project
3333
"ProjectViewSet",
3434
"AuditRuleViewSet",
@@ -51,4 +51,6 @@
5151
"OrganizationViewSet",
5252
# teams
5353
"TeamViewSet",
54+
# root
55+
"ApiV1RootView",
5456
)

src/aap_eda/api/views/root.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Copyright 2024 Red Hat, Inc.
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+
16+
import logging
17+
18+
from django.conf import settings
19+
from django.urls import URLPattern, URLResolver
20+
from rest_framework.response import Response
21+
from rest_framework.reverse import reverse
22+
from rest_framework.views import APIView
23+
24+
LOGGER = logging.getLogger(__name__)
25+
26+
27+
class ApiV1RootView(APIView):
28+
def get(self, request, *args, **kwargs):
29+
urls = get_api_v1_urls(request=request)
30+
return Response(urls)
31+
32+
33+
def get_api_v1_urls(request=None):
34+
from aap_eda.api import urls
35+
36+
def list_urls(urls):
37+
url_list = {}
38+
for url in urls:
39+
if isinstance(url, URLResolver):
40+
url_list.update(list_urls(url.url_patterns))
41+
elif isinstance(url, URLPattern):
42+
name = url.name
43+
if not name:
44+
LOGGER.warning(
45+
"URL %s has no name, DRF browsable API will omit it",
46+
url.pattern,
47+
)
48+
continue
49+
if url.pattern.regex.groups:
50+
continue
51+
url_list[name] = reverse(name, request=request)
52+
return url_list
53+
54+
if settings.ALLOW_LOCAL_RESOURCE_MANAGEMENT:
55+
urls = urls.v1_urls
56+
else:
57+
urls = urls.eda_v1_urls
58+
59+
return list_urls(urls)

src/aap_eda/settings/default.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ def _get_databases_settings() -> dict:
302302
# https://docs.djangoproject.com/en/4.1/howto/static-files/
303303

304304
STATIC_URL = "static/"
305+
STATIC_ROOT = settings.get("STATIC_ROOT", "/var/lib/eda/static")
305306

306307
MEDIA_ROOT = settings.get("MEDIA_ROOT", "/var/lib/eda/files")
307308

tests/integration/api/test_v1_root.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Copyright 2024 Red Hat, Inc.
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+
import pytest
15+
16+
from tests.integration.constants import api_url_v1
17+
18+
19+
@pytest.mark.parametrize(
20+
"expected_slugs,use_shared_resource",
21+
[
22+
pytest.param(
23+
[
24+
"/status/",
25+
"/openapi.json",
26+
"/openapi.yaml",
27+
"/docs",
28+
"/redoc",
29+
"/auth/session/login/",
30+
"/auth/session/logout/",
31+
"/auth/token/refresh/",
32+
"/users/me/",
33+
"/projects/",
34+
"/rulebooks/",
35+
"/activations/",
36+
"/activation-instances/",
37+
"/audit-rules/",
38+
"/users/",
39+
"/event-streams/",
40+
"/users/me/awx-tokens/",
41+
"/credential-types/",
42+
"/eda-credentials/",
43+
"/decision-environments/",
44+
"/organizations/",
45+
"/teams/",
46+
],
47+
True,
48+
id="with_shared_resource",
49+
),
50+
pytest.param(
51+
[
52+
"/status/",
53+
"/role_definitions/",
54+
"/role_user_assignments/",
55+
"/role_team_assignments/",
56+
"/role_metadata/",
57+
"/service-index/metadata/",
58+
"/service-index/validate-local-account/",
59+
"/service-index/resources/",
60+
"/service-index/resource-types/",
61+
"/service-index/",
62+
"/openapi.json",
63+
"/openapi.yaml",
64+
"/docs",
65+
"/redoc",
66+
"/auth/session/login/",
67+
"/auth/session/logout/",
68+
"/auth/token/refresh/",
69+
"/users/me/",
70+
"/projects/",
71+
"/rulebooks/",
72+
"/activations/",
73+
"/activation-instances/",
74+
"/audit-rules/",
75+
"/users/",
76+
"/event-streams/",
77+
"/users/me/awx-tokens/",
78+
"/credential-types/",
79+
"/eda-credentials/",
80+
"/decision-environments/",
81+
"/organizations/",
82+
"/teams/",
83+
],
84+
False,
85+
id="no_shared_resource",
86+
),
87+
],
88+
)
89+
@pytest.mark.django_db
90+
def test_v1_root(admin_client, request, expected_slugs, use_shared_resource):
91+
if use_shared_resource:
92+
request.getfixturevalue("use_shared_resource_setting")
93+
response = admin_client.get(f"{api_url_v1}/")
94+
assert response.status_code == 200
95+
for slug in expected_slugs:
96+
assert any(
97+
slug in url for url in response.data.values()
98+
), f"Expected slug {slug} not found in response"

tools/docker/docker-compose-dev-redis-tls.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ services:
8484
- /bin/bash
8585
- -c
8686
- >-
87-
aap-eda-manage migrate
87+
aap-eda-manage collectstatic --noinput
88+
&& aap-eda-manage migrate
8889
&& aap-eda-manage create_initial_data
8990
&& scripts/create_superuser.sh
9091
&& aap-eda-manage runserver 0.0.0.0:8000

tools/docker/docker-compose-dev.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ services:
100100
- /bin/bash
101101
- -c
102102
- >-
103-
aap-eda-manage migrate
103+
aap-eda-manage collectstatic --noinput
104+
&& aap-eda-manage migrate
104105
&& aap-eda-manage create_initial_data
105106
&& scripts/create_superuser.sh
106107
&& aap-eda-manage runserver 0.0.0.0:8000

tools/docker/docker-compose-mac.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ services:
5454
- /bin/bash
5555
- -c
5656
- >-
57-
aap-eda-manage migrate
57+
aap-eda-manage collectstatic --noinput
58+
&& aap-eda-manage migrate
5859
&& aap-eda-manage create_initial_data
5960
&& scripts/create_superuser.sh
6061
&& aap-eda-manage runserver 0.0.0.0:8000

tools/docker/docker-compose-stage.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ services:
7070
- /bin/bash
7171
- -c
7272
- >-
73-
aap-eda-manage migrate
73+
aap-eda-manage collectstatic --noinput
74+
&& aap-eda-manage migrate
7475
&& aap-eda-manage create_initial_data
7576
&& scripts/create_superuser.sh
7677
&& gunicorn -b 0.0.0.0:8000

0 commit comments

Comments
 (0)