Commit 0178d070 by Clinton Blackburn

Merge pull request #38 from edx/clintonb/api-gateway

API Gateway Setup
parents 5bc5bb59 9034de54
.DEFAULT_GOAL := test
.PHONY: clean compile_translations dummy_translations extract_translations fake_translations help html_coverage \
.PHONY: accept clean compile_translations dummy_translations extract_translations fake_translations help html_coverage \
migrate pull_translations push_translations quality requirements production-requirements test \
update_translations validate
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " help display this help message"
@echo " make accept run acceptance tests"
@echo " clean delete generated byte code and coverage reports"
@echo " compile_translations compile translation files, outputting .po files for each supported language"
@echo " dummy_translations generate dummy translation (.po) files"
......@@ -48,8 +49,8 @@ test: clean
coverage report
quality:
pep8 --config=.pep8 course_discovery *.py
pylint --rcfile=pylintrc course_discovery *.py
pep8 --config=.pep8 acceptance_tests course_discovery *.py
pylint --rcfile=pylintrc acceptance_tests course_discovery *.py
validate: test quality
......@@ -84,3 +85,6 @@ start-devstack:
open-devstack:
docker-compose --x-networking up -d
docker exec -it course-discovery env TERM=$(TERM) /edx/app/discovery/devstack.sh open
accept:
nosetests --with-ignore-docstrings -v acceptance_tests
import os
API_GATEWAY_DISCOVERY_ROOT = os.environ.get('API_GATEWAY_DISCOVERY_ROOT')
if not API_GATEWAY_DISCOVERY_ROOT:
raise RuntimeError('API_GATEWAY_DISCOVERY_ROOT (e.g. https://api.edx.org/discovery/v1) must be supplied!')
DISCOVERY_API_ACCESS_TOKEN = os.environ.get('DISCOVERY_API_ACCESS_TOKEN')
if not DISCOVERY_API_ACCESS_TOKEN:
raise RuntimeError('DISCOVERY_API_ACCESS_TOKEN must be supplied!')
CATALOG_ID = int(os.environ.get('CATALOG_ID', 1))
COURSE_ID = os.environ.get('COURSE_ID', 'edX/DemoX')
COURSE_RUN_ID = os.environ.get('COURSE_RUN_ID', 'course-v1:edX+DemoX+Demo_Course')
""" Tests to validate configuration of the API gateway. """
from unittest import TestCase
import ddt
import requests
from acceptance_tests.config import API_GATEWAY_DISCOVERY_ROOT, DISCOVERY_API_ACCESS_TOKEN, CATALOG_ID
@ddt.ddt
class ApiGatewayTests(TestCase):
PATHS = (
'catalogs/',
'catalogs/{id}/'.format(id=CATALOG_ID),
)
def get_discovery_api_gateway_url(self, path):
""" Returns a complete URL for the given path, routed through the API gateway. """
return '{root}/{path}'.format(root=API_GATEWAY_DISCOVERY_ROOT.rstrip('/'), path=path)
def assert_api_response(self, path, expected_status_code=200, **headers):
"""
Verify the API returns HTTP 200.
Arguments:
path(str) -- Path of the API endpoint to call.
expected_status_code (int) -- Expected HTTP status code of the API response.
headers (dict) -- Headers to pass with the request.
"""
url = self.get_discovery_api_gateway_url(path)
response = requests.get(url, headers=headers)
self.assertEqual(response.status_code, expected_status_code)
@ddt.data(*PATHS)
def test_endpoint_ok(self, path):
""" Verify the endpoint returns HTTP 200 for valid requests. """
headers = {
'Authorization': 'Bearer {token}'.format(token=DISCOVERY_API_ACCESS_TOKEN)
}
self.assert_api_response(path, **headers)
@ddt.data(*PATHS)
def test_endpoint_not_authorized(self, path):
""" Verify the endpoint returns HTTP 403 for unauthorized requests. """
self.assert_api_response(path, expected_status_code=403)
# Discovery IDA: upstream API definitions, including vendor extensions.
# Note, while this document is not strictly to Swagger spec, each HTTP method"s
# definition _must_ be to spec or the downstream ref will fail.
apigateway_responses: &apigateway_responses
default:
statusCode: "400"
200:
statusCode: "200"
401:
statusCode: "401"
403:
statusCode: "403"
404:
statusCode: "404"
429:
statusCode: "429"
500:
statusCode: "500"
produces: &produces
- "application/json"
- "application/csv"
responses: &responses
200:
description: "OK"
400:
description: "Bad Request"
401:
description: "Unauthorized"
403:
description: "Forbidden"
404:
description: "Not Found"
429:
description: "Too Many Requests"
500:
description: "Internal Server Error"
id_parameter: &id_parameter
name: "id"
in: "path"
required: true
type: "number"
auth_header: &auth_header
name: "Authorization"
in: "header"
required: true
type: "string"
# AWS API Gateway vendor extension point. This information is used
# by https://github.com/awslabs/aws-apigateway-importer.
x-amazon-apigateway-integration: &apigateway_integration
responses: *apigateway_responses
httpMethod: "GET"
type: "http"
requestParameters:
integration.request.header.Authorization: "method.request.header.Authorization"
x-amazon-apigateway-integration-with-id: &apigateway_integration_with_id_parameter
responses: *apigateway_responses
httpMethod: "GET"
type: "http"
requestParameters:
integration.request.header.Authorization: "method.request.header.Authorization"
integration.request.path.id: "method.request.path.id"
endpoints:
v1:
# /v1/catalogs
catalogs:
get:
produces: *produces
parameters:
- *auth_header
operationId: "get_catalogs"
responses: *responses
x-amazon-apigateway-integration:
<<: *apigateway_integration
uri: "https://${stageVariables.discovery_host}/v1/catalogs/"
# /v1/catalogs/{id}
catalogsById:
get:
produces: *produces
parameters:
- *auth_header
- *id_parameter
operationId: "get_catalogs_by_id"
responses: *responses
x-amazon-apigateway-integration:
<<: *apigateway_integration_with_id_parameter
uri: "https://${stageVariables.discovery_host}/v1/catalogs/{id}/"
# This file is a "de-compacted" version of api-compact.yaml. The consuming tools are unable to process YAML anchors.
# This file was generated using http://www.yamllint.com/.
---
endpoints:
v1:
catalogs:
get:
operationId: get_catalogs
parameters:
-
in: header
name: Authorization
required: true
type: string
produces:
- application/json
- application/csv
responses:
200:
description: OK
400:
description: "Bad Request"
401:
description: Unauthorized
403:
description: Forbidden
404:
description: "Not Found"
429:
description: "Too Many Requests"
500:
description: "Internal Server Error"
x-amazon-apigateway-integration:
httpMethod: GET
requestParameters:
integration.request.header.Authorization: method.request.header.Authorization
responses:
200:
statusCode: "200"
401:
statusCode: "401"
403:
statusCode: "403"
404:
statusCode: "404"
429:
statusCode: "429"
500:
statusCode: "500"
default:
statusCode: "400"
type: http
uri: "https://${stageVariables.discovery_host}/v1/catalogs/"
catalogsById:
get:
operationId: get_catalogs_by_id
parameters:
-
in: header
name: Authorization
required: true
type: string
-
in: path
name: id
required: true
type: number
produces:
- application/json
- application/csv
responses:
200:
description: OK
400:
description: "Bad Request"
401:
description: Unauthorized
403:
description: Forbidden
404:
description: "Not Found"
429:
description: "Too Many Requests"
500:
description: "Internal Server Error"
x-amazon-apigateway-integration:
httpMethod: GET
requestParameters:
integration.request.header.Authorization: method.request.header.Authorization
integration.request.path.id: method.request.path.id
responses:
200:
statusCode: "200"
401:
statusCode: "401"
403:
statusCode: "403"
404:
statusCode: "404"
429:
statusCode: "429"
500:
statusCode: "500"
default:
statusCode: "400"
type: http
uri: "https://${stageVariables.discovery_host}/v1/catalogs/{id}/"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment