Implementing poc spec behavior in append route.
This commit is contained in:
+21
-8
@@ -16,11 +16,12 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
from urllib.parse import urlparse
|
|
||||||
from itertools import repeat
|
from itertools import repeat
|
||||||
|
from urllib.parse import urlparse
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
import asyncio
|
import asyncio
|
||||||
import io
|
import io
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import shlex
|
import shlex
|
||||||
@@ -280,13 +281,25 @@ def append_route(app):
|
|||||||
app.router._frozen = False
|
app.router._frozen = False
|
||||||
content = await request.json()
|
content = await request.json()
|
||||||
name = "ROUTE_" + str(uuid4()).replace('-', '_')
|
name = "ROUTE_" + str(uuid4()).replace('-', '_')
|
||||||
app.router.add_route(content["method"],
|
try:
|
||||||
content["url_pattern"],
|
app.router.add_route(content["method"],
|
||||||
handle_route(content["entrypoint"],
|
content["url_pattern"],
|
||||||
content["command"]),
|
handle_route(content["entrypoint"],
|
||||||
name=name)
|
content["command"]),
|
||||||
print(f'Route created {content["method"]} {content["url_pattern"]}')
|
name=name)
|
||||||
return web.json_response(name)
|
except KeyError as exc:
|
||||||
|
missing = list()
|
||||||
|
for field in ("method", "url_pattern", "entrypoint", "command"):
|
||||||
|
if field not in content:
|
||||||
|
missing.append(field)
|
||||||
|
return web.Response(status=422,
|
||||||
|
reason="Missing Mandatory Field",
|
||||||
|
body=json.dumps({"missing_mandatory_fields": missing}))
|
||||||
|
except ValueError as exc:
|
||||||
|
return web.Response(status=422, reason="Invalid Route Spec")
|
||||||
|
else:
|
||||||
|
print(f'Route created {content["method"]} {content["url_pattern"]}')
|
||||||
|
return web.json_response(name)
|
||||||
return _append_route
|
return _append_route
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
@@ -15,8 +15,8 @@ Feature: Kapow! server reject responses with semantic errors.
|
|||||||
Then I get 422 as response code
|
Then I get 422 as response code
|
||||||
And I get "Missing Mandatory Field" as response reason phrase
|
And I get "Missing Mandatory Field" as response reason phrase
|
||||||
And I get the following entity as response body:
|
And I get the following entity as response body:
|
||||||
| missing_mandatory_fields |
|
| missing_mandatory_fields |
|
||||||
| "url_pattern", "method" |
|
| ["url_pattern", "method"] |
|
||||||
|
|
||||||
Scenario: Error because of wrong route specification.
|
Scenario: Error because of wrong route specification.
|
||||||
If a request contains an invalid expression in the
|
If a request contains an invalid expression in the
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import subprocess
|
from contextlib import suppress
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
import json
|
||||||
import shlex
|
import shlex
|
||||||
import socket
|
import socket
|
||||||
from contextlib import suppress
|
import subprocess
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from environconfig import EnvironConfig, StringVar, IntVar
|
from environconfig import EnvironConfig, StringVar, IntVar, BooleanVar
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
class Env(EnvironConfig):
|
class Env(EnvironConfig):
|
||||||
#: How to run Kapow! server
|
#: How to run Kapow! server
|
||||||
@@ -20,6 +22,30 @@ class Env(EnvironConfig):
|
|||||||
|
|
||||||
KAPOW_BOOT_TIMEOUT = IntVar(default=10)
|
KAPOW_BOOT_TIMEOUT = IntVar(default=10)
|
||||||
|
|
||||||
|
KAPOW_DEBUG_TESTS = BooleanVar(default=True)
|
||||||
|
|
||||||
|
|
||||||
|
if Env.KAPOW_DEBUG_TESTS:
|
||||||
|
# These two lines enable debugging at httplib level
|
||||||
|
# (requests->urllib3->http.client) You will see the REQUEST,
|
||||||
|
# including HEADERS and DATA, and RESPONSE with HEADERS but without
|
||||||
|
# DATA. The only thing missing will be the response.body which is
|
||||||
|
# not logged.
|
||||||
|
try:
|
||||||
|
import http.client as http_client
|
||||||
|
except ImportError:
|
||||||
|
# Python 2
|
||||||
|
import httplib as http_client
|
||||||
|
http_client.HTTPConnection.debuglevel = 1
|
||||||
|
|
||||||
|
# You must initialize logging, otherwise you'll not see debug output.
|
||||||
|
logging.basicConfig()
|
||||||
|
logging.getLogger().setLevel(logging.DEBUG)
|
||||||
|
requests_log = logging.getLogger("requests.packages.urllib3")
|
||||||
|
requests_log.setLevel(logging.DEBUG)
|
||||||
|
requests_log.propagate = True
|
||||||
|
|
||||||
|
|
||||||
@given('I have a just started Kapow! server')
|
@given('I have a just started Kapow! server')
|
||||||
@given('I have a running Kapow! server')
|
@given('I have a running Kapow! server')
|
||||||
def step_impl(context):
|
def step_impl(context):
|
||||||
@@ -97,30 +123,32 @@ def step_impl(context):
|
|||||||
if not hasattr(context, 'table'):
|
if not hasattr(context, 'table'):
|
||||||
raise RuntimeError("A table must be set for this step.")
|
raise RuntimeError("A table must be set for this step.")
|
||||||
|
|
||||||
for row in context.table:
|
row = context.table[0]
|
||||||
response = requests.post(f"{Env.KAPOW_CONTROLAPI_URL}/routes",
|
context.response = requests.post(f"{Env.KAPOW_CONTROLAPI_URL}/routes",
|
||||||
json={h: row[h] for h in row.headings})
|
json={h: row[h] for h in row.headings})
|
||||||
response.raise_for_status()
|
|
||||||
|
|
||||||
|
|
||||||
@then('I get {code} as response code')
|
@then('I get {code} as response code')
|
||||||
def step_impl(context, code):
|
def step_impl(context, code):
|
||||||
raise NotImplementedError('STEP: Then I get unprocessable entity as response code')
|
assert context.response.status_code == int(code), f"Got {context.response.status_code} instead"
|
||||||
|
|
||||||
|
|
||||||
@then('I get "{reason}" as response reason phrase')
|
@then('I get "{reason}" as response reason phrase')
|
||||||
def step_impl(context, reason):
|
def step_impl(context, reason):
|
||||||
raise NotImplementedError('STEP: Then I get "Missing Mandatory Field" as response phrase')
|
assert context.response.reason == reason, f"Got {context.response.reason} instead"
|
||||||
|
|
||||||
|
|
||||||
@then('I get the following entity as response body')
|
@then('I get the following entity as response body')
|
||||||
def step_impl(context):
|
def step_impl(context):
|
||||||
raise NotImplementedError('STEP: Then I get the following entity as response body')
|
for row in context.table:
|
||||||
|
for name, value in row.items():
|
||||||
|
assert name in context.response.json(), f"Field {name} not present in {context.response.json()}"
|
||||||
|
assert set(json.loads(value)) == set(context.response.json()[name])
|
||||||
|
|
||||||
|
|
||||||
@then('I get an empty response body')
|
@then('I get an empty response body')
|
||||||
def step_impl(context):
|
def step_impl(context):
|
||||||
raise NotImplementedError('STEP: Then I get an empty response body')
|
assert context.response.content == b'', f"Response body is not empty. Got {context.response.content} instead."
|
||||||
|
|
||||||
|
|
||||||
@when('I delete the route with id "{id}"')
|
@when('I delete the route with id "{id}"')
|
||||||
|
|||||||
Reference in New Issue
Block a user