Skip to content

Commit

Permalink
[docs] Add submodule initialization documentation (interuss#235)
Browse files Browse the repository at this point in the history
Add submodule initialization documentation
  • Loading branch information
BenjaminPelletier authored and Shastick committed Oct 10, 2023
1 parent f94cd07 commit 426a571
Show file tree
Hide file tree
Showing 12 changed files with 427 additions and 484 deletions.
1 change: 0 additions & 1 deletion monitoring/monitorlib/mutate/rid.py
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,6 @@ class ISAChange(ImplicitDict):
notifications: Dict[str, ISAChangeNotification]
"""Mapping from USS base URL to change notification query"""


def put_isa(
area_vertices: List[s2sphere.LatLng],
alt_lo: float,
Expand Down
2 changes: 1 addition & 1 deletion monitoring/prober/infrastructure.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def wrapper_default_scope(*args, **kwargs):
resource_type_code_descriptions: Dict[ResourceType, str] = {}


# Next code: 368
# Next code: 370
def register_resource_type(code: int, description: str) -> ResourceType:
"""Register that the specified code refers to the described resource.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
from typing import Optional, List

import arrow
import s2sphere
import datetime

from monitoring.monitorlib.fetch import rid as fetch
from monitoring.monitorlib.mutate import rid as mutate
from monitoring.prober.infrastructure import register_resource_type
from monitoring.uss_qualifier.common_data_definitions import Severity
from monitoring.uss_qualifier.resources.astm.f3411.dss import DSSInstanceResource
from monitoring.uss_qualifier.resources.interuss.id_generator import IDGeneratorResource
from monitoring.uss_qualifier.resources.netrid.service_area import ServiceAreaResource
from monitoring.uss_qualifier.scenarios.astm.netrid.common.dss import utils
from monitoring.uss_qualifier.scenarios.astm.netrid.dss_wrapper import DSSWrapper
from monitoring.uss_qualifier.scenarios.scenario import GenericTestScenario

HUGE_VERTICES: List[s2sphere.LatLng] = [
s2sphere.LatLng.from_degrees(lng=130, lat=-23),
s2sphere.LatLng.from_degrees(lng=130, lat=-24),
s2sphere.LatLng.from_degrees(lng=132, lat=-24),
s2sphere.LatLng.from_degrees(lng=132, lat=-23),
]


class ISAValidation(GenericTestScenario):
"""Based on prober/rid/v2/test_isa_validation.py from the legacy prober tool."""

ISA_TYPE = register_resource_type(369, "ISA")

def __init__(
self,
dss: DSSInstanceResource,
id_generator: IDGeneratorResource,
isa: ServiceAreaResource,
):
super().__init__()
self._dss = (
dss.dss_instance
) # TODO: delete once _delete_isa_if_exists updated to use dss_wrapper
self._dss_wrapper = DSSWrapper(self, dss.dss_instance)
self._isa_id = id_generator.id_factory.make_id(ISAValidation.ISA_TYPE)
self._isa_version: Optional[str] = None
self._isa = isa.specification

now = arrow.utcnow().datetime
self._isa_start_time = self._isa.shifted_time_start(now)
self._isa_end_time = self._isa.shifted_time_end(now)
self._isa_area = [vertex.as_s2sphere() for vertex in self._isa.footprint]

def run(self):
self.begin_test_scenario()

self._setup_case()

self.begin_test_case("ISA Validation")
self.begin_test_step("ISA Validation")

self._isa_huge_area_check()
self._isa_empty_vertices_check()
self._isa_start_time_in_past()
self._isa_start_time_after_time_end()
self._isa_vertices_are_valid()

# TODO Add these: they require omitting things from the request payload
# so we need to bypass the DSSWrapper
# - 'test_isa_missing_outline'
# - 'test_isa_missing_volume'
# - 'test_isa_missing_extents'

self.end_test_step()
self.end_test_case()
self.end_test_scenario()

def _setup_case(self):
self.begin_test_case("Setup")

def _ensure_clean_workspace_step():
self.begin_test_step("Ensure clean workspace")

self._delete_isa_if_exists()

self.end_test_step()

_ensure_clean_workspace_step()

self.end_test_case()

def _delete_isa_if_exists(self):
utils.delete_isa_if_exists(
self,
isa_id=self._isa_id,
rid_version=self._dss.rid_version,
session=self._dss.client,
server_id=self._dss_wrapper.participant_id,
)

def _isa_huge_area_check(self):

with self.check("ISA huge area", [self._dss_wrapper.participant_id]) as check:

self._dss_wrapper.put_isa_expect_response_code(
check=check,
expected_error_codes={400},
area_vertices=HUGE_VERTICES,
alt_lo=self._isa.altitude_min,
alt_hi=self._isa.altitude_max,
start_time=self._isa_start_time,
end_time=self._isa_end_time,
uss_base_url=self._isa.base_url,
isa_id=self._isa_id,
isa_version=self._isa_version,
)

def _isa_empty_vertices_check(self):

with self.check(
"ISA empty vertices", [self._dss_wrapper.participant_id]
) as check:

self._dss_wrapper.put_isa_expect_response_code(
check=check,
expected_error_codes={400},
area_vertices=[],
alt_lo=self._isa.altitude_min,
alt_hi=self._isa.altitude_max,
start_time=self._isa_start_time,
end_time=self._isa_end_time,
uss_base_url=self._isa.base_url,
isa_id=self._isa_id,
isa_version=self._isa_version,
)

def _isa_start_time_in_past(self):
time_start = datetime.datetime.utcnow() - datetime.timedelta(minutes=10)
time_end = time_start + datetime.timedelta(minutes=60)

with self.check(
"ISA start time in the past", [self._dss_wrapper.participant_id]
) as check:

self._dss_wrapper.put_isa_expect_response_code(
check=check,
expected_error_codes={400},
area_vertices=self._isa_area,
alt_lo=self._isa.altitude_min,
alt_hi=self._isa.altitude_max,
start_time=time_start,
end_time=time_end,
uss_base_url=self._isa.base_url,
isa_id=self._isa_id,
isa_version=self._isa_version,
)

def _isa_start_time_after_time_end(self):
with self.check(
"ISA start time after end time", [self._dss_wrapper.participant_id]
) as check:

self._dss_wrapper.put_isa_expect_response_code(
check=check,
expected_error_codes={400},
area_vertices=self._isa_area,
alt_lo=self._isa.altitude_min,
alt_hi=self._isa.altitude_max,
start_time=self._isa.time_end.datetime,
end_time=self._isa.time_start.datetime,
uss_base_url=self._isa.base_url,
isa_id=self._isa_id,
isa_version=self._isa_version,
)

def _isa_vertices_are_valid(self):
INVALID_VERTICES: List[s2sphere.LatLng] = [
s2sphere.LatLng.from_degrees(lat=130, lng=-23),
s2sphere.LatLng.from_degrees(lat=130, lng=-24),
s2sphere.LatLng.from_degrees(lat=132, lng=-24),
s2sphere.LatLng.from_degrees(lat=132, lng=-23),
]

with self.check(
"ISA vertices are valid", [self._dss_wrapper.participant_id]
) as check:

self._dss_wrapper.put_isa_expect_response_code(
check=check,
expected_error_codes={400},
area_vertices=INVALID_VERTICES,
alt_lo=self._isa.altitude_min,
alt_hi=self._isa.altitude_max,
start_time=self._isa.time_start.datetime,
end_time=self._isa.time_end.datetime,
uss_base_url=self._isa.base_url,
isa_id=self._isa_id,
isa_version=self._isa_version,
)

def cleanup(self):
self.begin_cleanup()

self._delete_isa_if_exists()

self.end_cleanup()
62 changes: 62 additions & 0 deletions monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from typing import Optional

from monitoring.monitorlib.fetch import rid as fetch
from monitoring.monitorlib.mutate import rid as mutate
from monitoring.monitorlib.infrastructure import UTMClientSession
from monitoring.monitorlib.rid import RIDVersion
from monitoring.uss_qualifier.common_data_definitions import Severity
from monitoring.uss_qualifier.scenarios.scenario import GenericTestScenario


def delete_isa_if_exists(
scenario: GenericTestScenario,
isa_id: str,
rid_version: RIDVersion,
session: UTMClientSession,
server_id: Optional[str] = None,
):
fetched = fetch.isa(
isa_id,
rid_version=rid_version,
session=session,
server_id=server_id,
)
scenario.record_query(fetched.query)
with scenario.check("Successful ISA query", [server_id]) as check:
if not fetched.success and fetched.status_code != 404:
check.record_failed(
"ISA information could not be retrieved",
Severity.High,
f"{server_id} DSS instance returned {fetched.status_code} when queried for ISA {isa_id}",
query_timestamps=[fetched.query.request.timestamp],
)

if fetched.success:
deleted = mutate.delete_isa(
isa_id,
fetched.isa.version,
rid_version,
session,
server_id=server_id,
)
scenario.record_query(deleted.dss_query.query)
for subscriber_id, notification in deleted.notifications.items():
scenario.record_query(notification.query)
with scenario.check("Removed pre-existing ISA", [server_id]) as check:
if not deleted.dss_query.success:
check.record_failed(
"Could not delete pre-existing ISA",
Severity.High,
f"Attempting to delete ISA {isa_id} from the {server_id} DSS returned error {deleted.dss_query.status_code}",
query_timestamps=[deleted.dss_query.query.request.timestamp],
)
for subscriber_url, notification in deleted.notifications.items():
with scenario.check("Notified subscriber", [subscriber_url]) as check:
# TODO: Find a better way to identify a subscriber who couldn't be notified
if not notification.success:
check.record_failed(
"Could not notify ISA subscriber",
Severity.Medium,
f"Attempting to notify subscriber for ISA {isa_id} at {subscriber_url} resulted in {notification.status_code}",
query_timestamps=[notification.query.request.timestamp],
)
37 changes: 37 additions & 0 deletions monitoring/uss_qualifier/scenarios/astm/netrid/dss_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,43 @@ def get_isa_expect_response_code(

return isa

def put_isa_expect_response_code(
self,
check: PendingCheck,
expected_error_codes: Set[int],
area_vertices: List[s2sphere.LatLng],
alt_lo: float,
alt_hi: float,
start_time: datetime.datetime,
end_time: datetime.datetime,
uss_base_url: str,
isa_id: str,
isa_version: Optional[str] = None,
) -> ISAChange:
mutated_isa = mutate.put_isa(
area_vertices=area_vertices,
alt_lo=alt_lo,
alt_hi=alt_hi,
start_time=start_time,
end_time=end_time,
uss_base_url=uss_base_url,
isa_id=isa_id,
isa_version=isa_version,
rid_version=self._dss.rid_version,
utm_client=self._dss.client,
server_id=self._dss.participant_id,
)

self._handle_query_result(
check=check,
q=mutated_isa.dss_query,
fail_msg="ISA Put succeeded when expecting a failure",
required_status_code=expected_error_codes,
severity=Severity.High,
fail_details=f"The submitted query was expected to fail. Payload: {mutated_isa.dss_query.query.request.json}",
)
return mutated_isa

def put_isa(
self,
main_check: PendingCheck,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .isa_simple import ISASimple
from .isa_validation import ISAValidation
from .subscription_validation import SubscriptionValidation
from .crdb_access import CRDBAccess
Loading

0 comments on commit 426a571

Please sign in to comment.