Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
M
Mapping Provider
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
geant-swd
Next Generation Map
Mapping Provider
Commits
a870a0cb
Commit
a870a0cb
authored
2 months ago
by
Erik Reid
Browse files
Options
Downloads
Patches
Plain Diff
added /services/<service-type>, and bugfix
parent
1d613d2c
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
mapping_provider/api/map.py
+15
-3
15 additions, 3 deletions
mapping_provider/api/map.py
mapping_provider/backends/services.py
+28
-23
28 additions, 23 deletions
mapping_provider/backends/services.py
test/test_map_endpoints.py
+50
-0
50 additions, 0 deletions
test/test_map_endpoints.py
with
93 additions
and
26 deletions
mapping_provider/api/map.py
+
15
−
3
View file @
a870a0cb
...
@@ -2,7 +2,7 @@ from typing import Any
...
@@ -2,7 +2,7 @@ from typing import Any
import
jsonschema
import
jsonschema
import
requests
import
requests
from
fastapi
import
APIRouter
from
fastapi
import
APIRouter
,
HTTPException
from
pydantic
import
BaseModel
from
pydantic
import
BaseModel
from
mapping_provider
import
config
from
mapping_provider
import
config
...
@@ -128,9 +128,21 @@ def get_equipment() -> EquipmentList:
...
@@ -128,9 +128,21 @@ def get_equipment() -> EquipmentList:
return
EquipmentList
(
equipment
=
list
(
map
(
_make_equipment
,
equipment_list_obj
)))
return
EquipmentList
(
equipment
=
list
(
map
(
_make_equipment
,
equipment_list_obj
)))
@router.get
(
"
/services
"
)
@router.get
(
"
/services/{service_type}
"
)
def
get_services
(
service_type
:
str
|
None
=
None
)
->
services
.
ServiceList
:
"""
handler for /trunks
"""
return_value
=
services
.
build_service_info_list
(
service_type
=
service_type
)
if
not
return_value
.
services
:
raise
HTTPException
(
status_code
=
404
,
detail
=
f
'
unrecognized service type:
{
service_type
}
'
)
return
return_value
@router.get
(
"
/trunks
"
)
@router.get
(
"
/trunks
"
)
def
get_trunks
()
->
services
.
ServiceList
:
def
get_trunks
()
->
services
.
ServiceList
:
"""
"""
handler for /trunks
handler for /trunks
, same as /services/IP TRUNK
"""
"""
return
services
.
build_service_info_list
(
service_type
=
'
IP TRUNK
'
)
return
get_
services
(
service_type
=
'
IP TRUNK
'
)
This diff is collapsed.
Click to expand it.
mapping_provider/backends/services.py
+
28
−
23
View file @
a870a0cb
...
@@ -30,6 +30,7 @@ class Service(BaseModel):
...
@@ -30,6 +30,7 @@ class Service(BaseModel):
name
:
str
name
:
str
type
:
str
type
:
str
pops
:
list
[
str
]
pops
:
list
[
str
]
equipment
:
list
[
str
]
overlays
:
Overlays
overlays
:
Overlays
...
@@ -37,8 +38,11 @@ class ServiceList(BaseModel):
...
@@ -37,8 +38,11 @@ class ServiceList(BaseModel):
services
:
list
[
Service
]
services
:
list
[
Service
]
def
endpoint_to_pop
(
endpoint
:
dict
[
str
,
Any
],
inprov_equipment_dict
:
dict
[
str
,
dict
[
str
,
Any
]])
->
str
:
def
endpoint_equipment
(
endpoint
:
dict
[
str
,
Any
])
->
str
:
"""
convert the correlator router hostname or optical equipment name
to the inventory equipment format
"""
def
_hostname_to_equipment
(
_hn
:
str
)
->
str
:
def
_hostname_to_equipment
(
_hn
:
str
)
->
str
:
m
=
re
.
match
(
r
'
^(.+)\.geant\.net$
'
,
_hn
)
m
=
re
.
match
(
r
'
^(.+)\.geant\.net$
'
,
_hn
)
if
not
m
:
if
not
m
:
...
@@ -47,21 +51,12 @@ def endpoint_to_pop(endpoint: dict[str, Any], inprov_equipment_dict: dict[str, d
...
@@ -47,21 +51,12 @@ def endpoint_to_pop(endpoint: dict[str, Any], inprov_equipment_dict: dict[str, d
return
m
.
group
(
1
).
upper
()
return
m
.
group
(
1
).
upper
()
if
'
hostname
'
in
endpoint
:
if
'
hostname
'
in
endpoint
:
eq_name
=
_hostname_to_equipment
(
endpoint
[
'
hostname
'
])
return
_hostname_to_equipment
(
endpoint
[
'
hostname
'
])
elif
'
equipment
'
in
endpoint
:
elif
'
equipment
'
in
endpoint
:
eq_name
=
endpoint
[
'
equipment
'
]
return
endpoint
[
'
equipment
'
]
else
:
# should already be validated
raise
AssertionError
(
f
'
no equipment or hostname in endpoint:
{
endpoint
}
'
)
if
eq_name
not
in
inprov_equipment_dict
:
# TODO: is this really possible if all data is read from IMS at the same time?
logger
.
error
(
f
'
unknown endpoint equipment:
{
eq_name
}
'
)
return
'
?
'
pop_name
=
inprov_equipment_dict
[
eq_name
][
'
pop
'
]
# should already be validated
assert
isinstance
(
pop_name
,
str
)
# mypy noise
raise
AssertionError
(
f
'
no equipment or hostname in endpoint:
{
endpoint
}
'
)
return
pop_name
def
_services
(
service_type
:
str
|
None
=
None
)
->
Generator
[
Service
]:
def
_services
(
service_type
:
str
|
None
=
None
)
->
Generator
[
Service
]:
...
@@ -92,7 +87,15 @@ def _services(service_type: str | None = None) -> Generator[Service]:
...
@@ -92,7 +87,15 @@ def _services(service_type: str | None = None) -> Generator[Service]:
brian_scid_rates
=
{
r
[
'
scid
'
]:
r
[
'
values
'
]
for
r
in
brian_rates
}
brian_scid_rates
=
{
r
[
'
scid
'
]:
r
[
'
values
'
]
for
r
in
brian_rates
}
equipment_dict
=
{
_x
[
'
name
'
]:
_x
for
_x
in
equipment_list
}
equipment_dict
=
{
_x
[
'
name
'
]:
_x
for
_x
in
equipment_list
}
_endpoint_to_pop
=
functools
.
partial
(
endpoint_to_pop
,
inprov_equipment_dict
=
equipment_dict
)
def
_get_equipment_pop
(
equipment_name
:
str
)
->
str
:
if
equipment_name
not
in
equipment_dict
:
# TODO: is this really possible if all data is read from IMS at the same time?
logger
.
error
(
f
'
unknown endpoint equipment:
{
equipment_name
}
'
)
return
'
?
'
_pop_name
=
equipment_dict
[
equipment_name
][
'
pop
'
]
assert
isinstance
(
_pop_name
,
str
)
# mypy noise
return
_pop_name
for
_s
in
scid_current
:
for
_s
in
scid_current
:
...
@@ -102,23 +105,24 @@ def _services(service_type: str | None = None) -> Generator[Service]:
...
@@ -102,23 +105,24 @@ def _services(service_type: str | None = None) -> Generator[Service]:
if
service_type
and
_s
[
'
service_type
'
]
!=
service_type
:
if
service_type
and
_s
[
'
service_type
'
]
!=
service_type
:
continue
continue
pops
=
sorted
(
set
(
map
(
_endpoint_to_pop
,
_s
[
'
endpoints
'
])))
equipment
=
sorted
(
set
(
map
(
endpoint_equipment
,
_s
[
'
endpoints
'
])))
pops
=
sorted
(
set
(
map
(
_get_equipment_pop
,
equipment
)))
rates
=
brian_scid_rates
.
get
(
_s
[
'
scid
'
],
{})
rates
=
brian_scid_rates
.
get
(
_s
[
'
scid
'
],
{})
overlays
=
Overlays
(
overlays
=
Overlays
(
speed
=
_s
[
'
speed
'
],
speed
=
_s
[
'
speed
'
],
up
=
_s
[
'
sid
'
]
not
in
down_service_sids
,
up
=
_s
[
'
sid
'
]
not
in
down_service_sids
,
latest
=
BitRates
(
latest
=
BitRates
(
egress
=
rates
[
'
latest
'
][
'
egress
'
]
,
egress
=
rates
.
get
(
'
latest
'
,
{}).
get
(
'
egress
'
)
,
ingress
=
rates
[
'
latest
'
][
'
ingress
'
]
,
ingress
=
rates
.
get
(
'
latest
'
,
{}).
get
(
'
ingress
'
)
,
),
),
mean
=
BitRates
(
mean
=
BitRates
(
egress
=
rates
[
'
mean
'
][
'
egress
'
]
,
egress
=
rates
.
get
(
'
mean
'
,
{}).
get
(
'
egress
'
)
,
ingress
=
rates
[
'
mean
'
][
'
ingress
'
]
,
ingress
=
rates
.
get
(
'
mean
'
,
{}).
get
(
'
ingress
'
)
,
),
),
max
=
BitRates
(
max
=
BitRates
(
egress
=
rates
[
'
max
'
][
'
egress
'
]
,
egress
=
rates
.
get
(
'
max
'
,
{}).
get
(
'
egress
'
)
,
ingress
=
rates
[
'
max
'
][
'
ingress
'
]
,
ingress
=
rates
.
get
(
'
max
'
,
{}).
get
(
'
ingress
'
)
,
),
),
)
)
...
@@ -128,6 +132,7 @@ def _services(service_type: str | None = None) -> Generator[Service]:
...
@@ -128,6 +132,7 @@ def _services(service_type: str | None = None) -> Generator[Service]:
name
=
_s
[
'
name
'
],
name
=
_s
[
'
name
'
],
type
=
_s
[
'
service_type
'
],
type
=
_s
[
'
service_type
'
],
pops
=
pops
,
pops
=
pops
,
equipment
=
equipment
,
overlays
=
overlays
,
overlays
=
overlays
,
)
)
...
...
This diff is collapsed.
Click to expand it.
test/test_map_endpoints.py
+
50
−
0
View file @
a870a0cb
import
re
import
re
import
pytest
import
responses
import
responses
from
mapping_provider.api.map
import
EquipmentList
,
PopList
from
mapping_provider.api.map
import
EquipmentList
,
PopList
...
@@ -38,9 +39,58 @@ def test_get_equipment(client):
...
@@ -38,9 +39,58 @@ def test_get_equipment(client):
assert
equipment_list
.
equipment
,
'
test data should not be empty
'
assert
equipment_list
.
equipment
,
'
test data should not be empty
'
@responses.activate
@pytest.mark.parametrize
(
'
service_type
'
,
[
'
IP PEERING - R&E
'
,
'
GEANT SPECTRUM SERVICE
'
,
'
L3-VPN
'
,
'
OOB IP LINK
'
,
'
GEANT OPEN CROSS CONNECT
'
,
'
GEANT - GBS
'
,
'
GWS - INDIRECT
'
,
'
GEANT IP
'
,
'
POP LAN LINK
'
,
'
IP PEERING - NON R&E (PUBLIC)
'
,
'
IP TRUNK
'
,
'
GEANT PLUS
'
,
'
L2SERVICES
'
,
'
ETHERNET
'
,
'
EUMETSAT TERRESTRIAL
'
,
'
IP PEERING - NON R&E (PRIVATE)
'
,
'
EXPRESS ROUTE
'
,
'
CBL1
'
,
'
GWS - UPSTREAM
'
,
'
GEANT PEERING
'
,
'
SERVER LINK
'
,
'
GEANT MANAGED WAVELENGTH SERVICE
'
,
'
CORPORATE
'
,
'
EUMETSAT GRE
'
])
def
test_get_services
(
client
,
service_type
):
rv
=
client
.
get
(
f
"
/map/services/
{
service_type
}
"
)
assert
rv
.
status_code
==
200
service_list
=
ServiceList
.
model_validate
(
rv
.
json
())
assert
service_list
.
services
,
'
test data should not be empty
'
assert
all
(
s
.
type
==
service_type
for
s
in
service_list
.
services
)
def
test_get_unknown_service_type
(
client
):
rv
=
client
.
get
(
f
"
/map/services/BOGUS_SERVICE_TYPE
"
)
assert
rv
.
status_code
==
404
def
test_get_all_services
(
client
):
rv
=
client
.
get
(
"
/map/services
"
)
assert
rv
.
status_code
==
200
service_list
=
ServiceList
.
model_validate
(
rv
.
json
())
assert
service_list
.
services
,
'
test data should not be empty
'
@responses.activate
@responses.activate
def
test_get_trunks
(
client
):
def
test_get_trunks
(
client
):
rv
=
client
.
get
(
"
/map/trunks
"
)
rv
=
client
.
get
(
"
/map/trunks
"
)
assert
rv
.
status_code
==
200
assert
rv
.
status_code
==
200
service_list
=
ServiceList
.
model_validate
(
rv
.
json
())
service_list
=
ServiceList
.
model_validate
(
rv
.
json
())
assert
service_list
.
services
,
'
test data should not be empty
'
assert
service_list
.
services
,
'
test data should not be empty
'
assert
all
(
s
.
type
==
'
IP TRUNK
'
for
s
in
service_list
.
services
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment