Skip to content

Commit 5f0f220

Browse files
authored
Metadata API endpoint to display server information (#507)
1 parent 8104b9e commit 5f0f220

File tree

10 files changed

+121
-9
lines changed

10 files changed

+121
-9
lines changed

.github/workflows/tox.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,9 @@ jobs:
8282
runs-on: ubuntu-24.04
8383
needs:
8484
- tox
85-
# if: github.ref == 'refs/heads/main'
86-
# github.event_name == 'release' && github.event.action == 'published'
85+
if: github.ref == 'refs/heads/main'
86+
# This condition ensures that publishing can only happen on push events to the main branch.
87+
# Pull request events are excluded as they don't have the necessary permissions to publish.
8788
steps:
8889
- name: Check out repository
8990
uses: actions/checkout@v4

src/ansible_dev_tools/resources/server/data/openapi.yaml

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
openapi: 3.1.0
22
info:
3-
title: Playbook Creator API
3+
title: Ansible Development Tools APIs
44
version: 1.0.0
5-
description: API for ansible creator
5+
description: APIs for ansible development tools
66
paths:
7+
/metadata:
8+
get:
9+
summary: Retrieve versions of installed tools and existing API endpoints
10+
responses:
11+
"200":
12+
description: A list of installed tools and their versions
13+
content:
14+
application/json:
15+
schema:
16+
$ref: "#/components/schemas/Metadata"
717
/v1/creator/collection:
818
post:
919
summary: Create a new collection project
@@ -95,6 +105,19 @@ paths:
95105

96106
components:
97107
schemas:
108+
Metadata:
109+
type: object
110+
properties:
111+
versions:
112+
type: object
113+
additionalProperties:
114+
type: string
115+
apis:
116+
type: object
117+
additionalProperties:
118+
type: array
119+
items:
120+
type: string
98121
CreatorCollection:
99122
type: object
100123
additionalProperties: false
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""The Server Info API."""
2+
3+
from __future__ import annotations
4+
5+
from django.http import HttpRequest, JsonResponse
6+
from django.urls import get_resolver
7+
8+
from ansible_dev_tools.server_utils import validate_request
9+
from ansible_dev_tools.version_builder import version_builder
10+
11+
12+
class GetMetadata:
13+
"""The metadata, returns the available tools with their versions and available API endpoints."""
14+
15+
def server_info(self, request: HttpRequest) -> JsonResponse:
16+
"""Return server information including versions and available APIs.
17+
18+
Args:
19+
request: HttpRequest Object
20+
Returns:
21+
JSON response containing tool versions and available API endpoints.
22+
"""
23+
validate_request(request)
24+
versions = {}
25+
for line in version_builder().splitlines():
26+
tool, version = line.split(maxsplit=1)
27+
versions[tool] = version
28+
29+
resolver = get_resolver()
30+
urlpatterns = resolver.url_patterns
31+
32+
endpoints = [str(pattern.pattern) for pattern in urlpatterns]
33+
34+
grouped_endpoints: dict[str, list[str]] = {}
35+
36+
for endpoint in endpoints:
37+
parts = endpoint.split("/")
38+
key = parts[0]
39+
if key not in grouped_endpoints:
40+
grouped_endpoints[key] = []
41+
grouped_endpoints[key].append(f"/{endpoint}")
42+
43+
return JsonResponse({"versions": versions, "apis": grouped_endpoints}, status=200)

src/ansible_dev_tools/server_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import yaml
99

10-
from django.http import FileResponse, HttpRequest, HttpResponse
10+
from django.http import FileResponse, HttpRequest, HttpResponse, JsonResponse
1111
from openapi_core import OpenAPI
1212
from openapi_core.contrib.django import DjangoOpenAPIRequest, DjangoOpenAPIResponse
1313
from openapi_core.exceptions import OpenAPIError
@@ -26,7 +26,7 @@
2626
)
2727

2828

29-
def validate_request(request: HttpRequest) -> RequestUnmarshalResult | HttpResponse:
29+
def validate_request(request: HttpRequest) -> RequestUnmarshalResult | HttpResponse | JsonResponse:
3030
"""Validate the request against the OpenAPI schema.
3131
3232
Args:

src/ansible_dev_tools/subcommands/server.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414

1515
from ansible_dev_tools.resources.server.creator_v1 import CreatorFrontendV1
1616
from ansible_dev_tools.resources.server.creator_v2 import CreatorFrontendV2
17+
from ansible_dev_tools.resources.server.server_info import GetMetadata
1718

1819

1920
if TYPE_CHECKING:
2021
from django.core.handlers.wsgi import WSGIHandler
2122

2223

2324
urlpatterns = (
25+
path(route="metadata", view=GetMetadata().server_info, name="server_info"),
2426
path(route="v1/creator/playbook", view=CreatorFrontendV1().playbook),
2527
path(route="v1/creator/collection", view=CreatorFrontendV1().collection),
2628
path(route="v2/creator/playbook", view=CreatorFrontendV2().playbook),

tests/integration/test_container.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from .test_server_creator_v1 import test_collection_v1 as tst_collection_v1
1515
from .test_server_creator_v1 import test_error as tst_error
1616
from .test_server_creator_v1 import test_playbook_v1 as tst_playbook_v1
17+
from .test_server_info import test_metadata as tst_get_metadata
1718

1819

1920
if TYPE_CHECKING:
@@ -219,6 +220,16 @@ def test_playbook_v1_container(server_in_container_url: str, tmp_path: Path) ->
219220
tst_playbook_v1(server_url=server_in_container_url, tmp_path=tmp_path)
220221

221222

223+
@pytest.mark.container
224+
def test_get_metadata_container(server_in_container_url: str) -> None:
225+
"""Test the metadata endpoint.
226+
227+
Args:
228+
server_in_container_url: The dev tools server.
229+
"""
230+
tst_get_metadata(server_url=server_in_container_url)
231+
232+
222233
@pytest.mark.container
223234
def test_nav_collections(
224235
container_tmux: ContainerTmux,

tests/integration/test_server_info.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""Test the dev tools server for metadata."""
2+
3+
from __future__ import annotations
4+
5+
import requests
6+
7+
8+
def test_metadata(server_url: str) -> None:
9+
"""Test the server info endpoint.
10+
11+
Args:
12+
server_url: The server URL.
13+
"""
14+
endpoint = f"{server_url}/metadata"
15+
16+
response = requests.get(endpoint, timeout=10)
17+
18+
expected_response_code = 200
19+
assert (
20+
response.status_code == expected_response_code
21+
), f"Expected status code 200 but got {response.status_code}"
22+
23+
assert response.headers["Content-Type"] == "application/json"
24+
25+
data = response.json()
26+
27+
assert "versions" in data, "Response is missing 'versions' key"
28+
assert "apis" in data, "Response is missing 'apis' key"
29+
30+
assert len(data["versions"]) > 0, "Versions should contain at least one package"
31+
32+
assert len(data["apis"]) > 0, "APIs should contain at least one endpoint"

tools/devspaces.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ mk containers check $IMAGE_NAME --engine="${ADT_CONTAINER_ENGINE}" --max-size=16
3030

3131
pytest --only-container --container-engine="${ADT_CONTAINER_ENGINE}" --container-name=devspaces --image-name=$IMAGE_NAME "$@" || echo "::error::Ignored failed devspaces tests, please https://github.com/ansible/ansible-dev-tools/issues/467"
3232

33-
if [[ -n "${GITHUB_SHA:-}" ]]; then
33+
if [[ -n "${GITHUB_SHA:-}" && "${GITHUB_EVENT_NAME:-}" != "pull_request" ]]; then
3434
$ADT_CONTAINER_ENGINE tag $IMAGE_NAME "ghcr.io/ansible/ansible-devspaces-tmp:${GITHUB_SHA}"
3535
# https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry
3636
if [[ -n "${GITHUB_TOKEN:-}" ]]; then

tools/ee.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pushd docs/examples
8080
ansible-builder build
8181
popd
8282

83-
if [[ -n "${GITHUB_SHA:-}" ]]; then
83+
if [[ -n "${GITHUB_SHA:-}" && "${GITHUB_EVENT_NAME:-}" != "pull_request" ]]; then
8484
FQ_IMAGE_NAME="ghcr.io/ansible/community-ansible-dev-tools-tmp:${GITHUB_SHA}-$ARCH"
8585
$ADT_CONTAINER_ENGINE tag $IMAGE_NAME "${FQ_IMAGE_NAME}"
8686
# https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ commands =
116116
[testenv:ee]
117117
description =
118118
Build the ee container image
119-
skip_install = true
119+
skip_install = false
120120
deps =
121121
-r .config/requirements-test.in
122122
ansible-builder

0 commit comments

Comments
 (0)