diff --git a/src/README.md b/src/README.md index c242dca5e..01c627baa 100644 --- a/src/README.md +++ b/src/README.md @@ -522,6 +522,7 @@ Each cache in the list contains the following attributes: - `endpoint`: The `:` of the public (`xrootd@stash-cache`) service - `auth_endpoint`: The `:` of the authenticated (`xrootd@stash-cache-auth`) service - `resource`: The resource name of the cache. +- `production`: true if the resource is in "production" (as opposed to ITB) The JSON also contains an attribute `namespaces` that is a list of namespaces with the following attributes: - `path` is the path of the namespace @@ -553,11 +554,13 @@ The final result looks like { "auth_endpoint": "osg-gftp.pace.gatech.edu:8443", "endpoint": "osg-gftp.pace.gatech.edu:8000", + "production": true, "resource": "Georgia_Tech_PACE_GridFTP" }, { "auth_endpoint": "osg-gftp2.pace.gatech.edu:8443", "endpoint": "osg-gftp2.pace.gatech.edu:8000", + "production": true, "resource": "Georgia_Tech_PACE_GridFTP2" } ], @@ -567,6 +570,7 @@ The final result looks like { "auth_endpoint": "rds-cache.sdsc.edu:8443", "endpoint": "rds-cache.sdsc.edu:8000", + "production": true, "resource": "RDS_AUTH_OSDF_CACHE" } ], diff --git a/src/stashcache.py b/src/stashcache.py index 7145706e2..47eb6986d 100644 --- a/src/stashcache.py +++ b/src/stashcache.py @@ -564,7 +564,17 @@ def _service_resource_dict( if not is_null(svc, "Details", "auth_endpoint_override"): auth_endpoint = svc["Details"]["auth_endpoint_override"] break - return {"endpoint": endpoint, "auth_endpoint": auth_endpoint, "resource": r.name} + production = None + try: + production = bool(r.rg.production) + except AttributeError: + pass + return { + "endpoint": endpoint, + "auth_endpoint": auth_endpoint, + "resource": r.name, + "production": production, + } def _cache_resource_dict(r: Resource): return _service_resource_dict(r=r, service_name=XROOTD_CACHE_SERVER, auth_port_default=8443, unauth_port_default=8000) diff --git a/src/tests/test_api.py b/src/tests/test_api.py index c85d3eb96..a93672c9b 100644 --- a/src/tests/test_api.py +++ b/src/tests/test_api.py @@ -769,7 +769,8 @@ class TestEndpointContent: }, 'Tags': ['CC*'] } - mock_resource = Resource("AMNH-ARES", mock_resource_information, global_data.get_topology().common_data) + mock_resource = Resource("AMNH-ARES", mock_resource_information, global_data.get_topology().common_data, + mock_resource_group) mock_facility.add_site(mock_site) mock_site.add_resource_group(mock_resource_group) diff --git a/src/tests/test_stashcache.py b/src/tests/test_stashcache.py index f4573f68c..ac927ed1f 100644 --- a/src/tests/test_stashcache.py +++ b/src/tests/test_stashcache.py @@ -1,5 +1,6 @@ from configparser import ConfigParser import copy + import flask import pytest import re @@ -279,6 +280,7 @@ def validate_cache_schema(cc): assert HOST_PORT_RE.match(cc["auth_endpoint"]) assert HOST_PORT_RE.match(cc["endpoint"]) assert cc["resource"] and isinstance(cc["resource"], str) + assert "production" in cc and isinstance(cc["production"], (type(None), bool)) @staticmethod def validate_namespace_schema(ns): diff --git a/src/webapp/topology.py b/src/webapp/topology.py index e8ea800e0..bcb9b5671 100644 --- a/src/webapp/topology.py +++ b/src/webapp/topology.py @@ -109,7 +109,7 @@ def is_ccstar(self): return self._is_ccstar class Resource(object): - def __init__(self, name: str, yaml_data: ParsedYaml, common_data: CommonData): + def __init__(self, name: str, yaml_data: ParsedYaml, common_data: CommonData, rg: "ResourceGroup"): self.name = name self.service_types = common_data.service_types self.common_data = common_data @@ -124,6 +124,7 @@ def __init__(self, name: str, yaml_data: ParsedYaml, common_data: CommonData): raise ValueError(f"Resource {name} does not have an FQDN") self.fqdn = self.data["FQDN"] self.id = self.data["ID"] + self.rg = rg def get_stashcache_files(self, global_data, legacy): """Gets a resources Cache files as a dictionary""" @@ -378,14 +379,14 @@ def __init__(self, name: str, yaml_data: ParsedYaml, site: Site, common_data: Co self.support_center = OrderedDict([("ID", scid), ("Name", scname)]) self.resources_by_name = {} - for name, res in yaml_data["Resources"].items(): + for res_name, res in yaml_data["Resources"].items(): try: if not isinstance(res, dict): raise TypeError("expecting a dict") - res_obj = Resource(name, ParsedYaml(res), self.common_data) - self.resources_by_name[name] = res_obj + res_obj = Resource(res_name, ParsedYaml(res), self.common_data, rg=self) + self.resources_by_name[res_name] = res_obj except (AttributeError, KeyError, TypeError, ValueError) as err: - log.exception("Error with resource %s: %r", name, err) + log.exception("Error with resource %s: %r", res_name, err) continue self.data = yaml_data