Skip to content

Commit 3246e38

Browse files
authored
Merge pull request #33 from mcriscenzo/feature/custom_edfi_urls
Feature - Custom metadata URLs
2 parents 3579abf + b227fd4 commit 3246e38

3 files changed

Lines changed: 54 additions & 18 deletions

File tree

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ data_dir: ./
4343
namespace: ed-fi
4444
edfi_api:
4545
base_url: https://api.schooldistrict.org/v5.3/api
46+
oauth_url: https://api.schooldistrict.org/v5.3/api/oauth/token
47+
dependencies_url: https://api.schooldistrict.org/v5.3/api/metadata/data/v3/2024/dependencies
48+
descriptors_swagger_url: https://api.schooldistrict.org/v5.3/api/metadata/data/v3/2024/descriptors/swagger.json
49+
resources_swagger_url: https://api.schooldistrict.org/v5.3/api/metadata/data/v3/2024/resources/swagger.json
4650
version: 3
4751
mode: year_specific
4852
year: 2021
@@ -68,6 +72,11 @@ show_stacktrace: True
6872
* (optional) Specify the `namespace` to use when accessing the Ed-Fi API. The default is `ed-fi` but others include `tpdm` or custom values. To send data to multiple namespaces, you must use a YAML configuration file and `lightbeam send` for each.
6973
* Specify the details of the `edfi_api` to which to connect including
7074
* (optional) The `base_url` which serves a JSON object specifying the paths to data endpoints, Swagger, and dependencies. The default is `https://localhost/api` (the address of an Ed-Fi API [running locally in Docker](https://techdocs.ed-fi.org/display/EDFITOOLS/Docker+Deployment)), but the location varies depending on how Ed-Fi is deployed.
75+
* If the metadata for a particular API is not located in the "default" location (at the root of the base_url), then ALL the following urls should be explicitly specified. These can normally be left blank, unless you are encountering errors indicating that the metadata files cannot be found (such as "Could not parse response from [base_url]").
76+
* (optional) `oauth_url` (usually [base_url]/oauth/token)
77+
* (optional) `dependencies_url` (usually [base_url]/metadata/data/v3/dependencies)
78+
* (optional) `descriptors_swagger_url` (usually [base_url]/metadata/data/v3/descriptors/swagger.json)
79+
* (optional) `resources_swagger_url` (usually [base_url]/metadata/data/v3/resources/swagger.json)
7180
* The `version` as one of `3` or `2` (`2` is currently unsupported).
7281
* (optional) The `mode` as one of `shared_instance`, `sandbox`, `district_specific`, `year_specific`, or `instance_year_specific`.
7382
* (required if `mode` is `year_specific` or `instance_year_specific`) The `year` used to build the resource URL. The default is the current year.

lightbeam/api.py

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,22 @@ def prepare(self):
3535
except Exception as e:
3636
self.logger.critical("could not connect to {0} ({1})".format(self.config["base_url"], str(e)))
3737

38-
try:
39-
api_base = api_base.json()
40-
except Exception as e:
41-
self.logger.critical("could not parse response from {0} ({1})".format(self.config["base_url"], str(e)))
42-
43-
self.config["oauth_url"] = api_base["urls"]["oauth"]
44-
self.config["dependencies_url"] = api_base["urls"]["dependencies"]
38+
# Data URL doesn't rely on metadata connection
4539
self.config["data_url"] = self.get_data_url()
46-
self.config["open_api_metadata_url"] = api_base["urls"]["openApiMetadata"]
40+
41+
# If ALL urls are set in config (probably from source/destination file),
42+
# then they don't need to be pulled from api metadata, so this section can be skipped.
43+
# This is most common if the api metadata json files are not in the "default" location.
44+
# Otherwise, pull urls from api metadata.
45+
if self.config["oauth_url"] == "" or self.config["dependencies_url"]== "":
46+
try:
47+
api_base = api_base.json()
48+
except Exception as e:
49+
self.logger.critical("could not parse response from {0} ({1})".format(self.config["base_url"], str(e)))
50+
51+
self.config["oauth_url"] = api_base["urls"]["oauth"]
52+
self.config["dependencies_url"] = api_base["urls"]["dependencies"]
53+
self.config["open_api_metadata_url"] = api_base["urls"]["openApiMetadata"]
4754

4855
# load all endpoints in dependency-order
4956
all_endpoints = self.get_sorted_endpoints()
@@ -160,17 +167,33 @@ def get_sorted_endpoints(self):
160167

161168
# Loads the Swagger JSON from the Ed-Fi API
162169
def load_swagger_docs(self):
163-
# grab Descriptors and Resources swagger URLs
164-
try:
165-
self.logger.debug("fetching swagger docs...")
166-
response = requests.get(self.config["open_api_metadata_url"],
167-
verify=self.lightbeam.config["connection"]["verify_ssl"])
168-
if not response.ok:
169-
raise Exception("OpenAPI metadata URL returned status {0} ({1})".format(response.status_code, (response.content[:75] + "...") if len(response.content)>75 else response.content))
170-
openapi = response.json()
171170

172-
except Exception as e:
173-
self.logger.critical("Unable to load Swagger docs from API... terminating. Check API connectivity.")
171+
# If the metadata URL is set (pulled from root metadata file earlier), then pull endpoint urls from metadata
172+
if "open_api_metadata_url" in self.config.keys() and self.config["open_api_metadata_url"] != "":
173+
# grab Descriptors and Resources swagger URLs
174+
try:
175+
self.logger.debug("fetching swagger docs...")
176+
response = requests.get(self.config["open_api_metadata_url"],
177+
verify=self.lightbeam.config["connection"]["verify_ssl"])
178+
if not response.ok:
179+
raise Exception("OpenAPI metadata URL returned status {0} ({1})".format(response.status_code, (response.content[:75] + "...") if len(response.content)>75 else response.content))
180+
openapi = response.json()
181+
182+
except Exception as e:
183+
self.logger.critical("Unable to load Swagger docs from API... terminating. Check API connectivity.")
184+
185+
# If metadata URL is not found, set endpoint URLs from config file
186+
else:
187+
openapi = [
188+
{
189+
"name": "descriptors",
190+
"endpointUri": self.config["descriptors_swagger_url"],
191+
},
192+
{
193+
"name": "resources",
194+
"endpointUri": self.config["resources_swagger_url"],
195+
}
196+
]
174197

175198
# load (or re-use cached) Descriptors and Resources swagger
176199
self.descriptors_swagger = None

lightbeam/lightbeam.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ class Lightbeam:
2424
"namespace": "ed-fi",
2525
"edfi_api": {
2626
"base_url": "",
27+
"oauth_url": "",
28+
"dependencies_url": "",
29+
"descriptors_swagger_url": "",
30+
"resources_swagger_url": "",
2731
"version": 3,
2832
"mode": "year_specific",
2933
"year": datetime.today().year,

0 commit comments

Comments
 (0)