Closed xi-yang closed 3 years ago
Sprint 1 (March 1st - March 14th):
auth
)service
)Sprint 2 (March 15th - March 28th):
intent
)intent
and service
so that users can leverage helper functions in intent
for service
operations@scaly789 Here is a better way to work with the Keycloak authentication. Example code below.
import requests
from oauthlib.oauth2 import LegacyApplicationClient
from requests_oauthlib.oauth2_auth import OAuth2
from requests_oauthlib.oauth2_session import OAuth2Session
# the configs
token_url='https://dev1.virao.com:8543/auth/realms/StackV/protocol/openid-connect/token'
client_id = 'StackV'
client_secret='ae53fbea-8812-4c13-918f-0065a1550b7c'
username = 'xyang'
password = 'mypassword'
# the common code
oauth = OAuth2Session(client=LegacyApplicationClient(client_id=client_id))
token = oauth.fetch_token(token_url=token_url, username=username, password=password, client_id=client_id, client_secret=client_secret)
auth = OAuth2(client_id = client_id, token = token)
# example request
r = requests.get("https://dev1.virnao.com:8443/StackV-web/restapi/service/ready", auth=auth)
print(r.status_code)
print(r.text)
You can then wrap this script into a common API call function.
For auth, check to see if the auth in the get call automatically refreshes or not. Input data as a dictionary and data = data as an argument for requests.post
For auth, check to see if the auth in the get call automatically refreshes or not. Input data as a dictionary and data = data as an argument for requests.post
@scaly789 As we discussed, it is ok to get a new access token upon each API call. But this is not ideal. A better way is to reuse a token. If you got HTTP 401 (unauthorized) error, use refresh token to renew it. If refresh failed (401 again), you can throw an auth exception.
The procedure is explained here: https://community.atlassian.com/t5/Bitbucket-questions/Refresh-Tokens-using-Python-requests/qaq-p/1213162
Some additional comments there also explained why you need refresh, because user key / password etc. are not necessarily handy every time you make the call. In our case, we may have them all the time for now. But a more general procedure will be preferred for future proof.
@scaly789 Make sure you checked in the code to repo, even it is in progress.
For service
methods, use text (string) intent
instead of input_file
, as the source of intent is not necessarily from a file. Sometime access to local files is limited for clients. Also use a list of of intent
instead of a single one. We may have multiple versions of intents even though in most cases we only have one.
@scaly789 For testing, put some script under /test/ that will use the modules in rest of this repo to create auth client and make service calls. Some python UnitTest will be preferred.
Also, use a config file such as ~/.sense/config
to store the input (mainly user credentials like, client-id, key and password etc.). They load them into the auth client. Never put "real" credential directly in test code and push to github.
@juztas The above is FYI so that you can see the progress on the client package.
Sounds good. I just pushed my own structure I had pending for some time. You can see it here: https://github.com/sdn-sense/sense-o-py-client/tree/master/src/python/sense
Lets extend it from here.
Sounds good. I just pushed my own structure I had pending for some time. You can see it here: https://github.com/sdn-sense/sense-o-py-client/tree/master/src/python/sense
Lets extend it from here.
Excellent! Feel free to contribute design and codes, and provide guidance to @scaly789 along with the progress.
@scaly789
To be completely clear about the OAuth flow, here is what we should do.
if client has no refresh_token:
use user credential (username and password for now, and other mechanisms like web and MFA in the future) to get both access_token and refresh_token
store your refresh_token
make your (first) API call using the access_token
else:
try:
use refresh_token to get new access_token and refresh_token (w/o user credential
store new refresh_token
make API call using the new access_token
exception (401 error): # refresh_token expired
use user credential again to get both access_token and refresh_token
store new refresh_token
make API call using the access_token
We can wrap all these into one common function.
For auth, check to see if the auth in the get call automatically refreshes or not. Input data as a dictionary and data = data as an argument for requests.post
@scaly789 As we discussed, it is ok to get a new access token upon each API call. But this is not ideal. A better way is to reuse a token. If you got HTTP 401 (unauthorized) error, use refresh token to renew it. If refresh failed (401 again), you can throw an auth exception.
The procedure is explained here: https://community.atlassian.com/t5/Bitbucket-questions/Refresh-Tokens-using-Python-requests/qaq-p/1213162
Some additional comments there also explained why you need refresh, because user key / password etc. are not necessarily handy every time you make the call. In our case, we may have them all the time for now. But a more general procedure will be preferred for future proof.
@scaly789 Here is a Jupyter notebook example for an API client that creates "sliced" topology with the FABRIC testbed. FABRIC provides services similar to SENSE. In the Create Slice
section, you can see how it does a dictionary topology data structure that is comparable to our "intent", and what I meant by "composing / parsing into a data structure" instead of just load a single text string.
https://github.com/fabric-testbed/jupyternb-template/blob/master/fabric/basic/orchestrator.ipynb
The preceding authentication sections are by general OAuth flow, similar to what we are doing (not exactly the same).
For reference: https://www.oauth.com/oauth2-servers/making-authenticated-requests/refreshing-an-access-token/
I also left my terminal for more than 20mins (while expires_in is 300s) - I can still use my old token (without refreshing). @xi-yang something is weird here - it should expire in 300s, but it is not.
Simple test:
from sense.client import Client
client = Client()
Once Client()
is called - it will get a new token.
So the logic is:
First initialization - call `Client()` - will get token. If this fails for any reasons - need to catch possible exceptions (401, 403, 500)
in _getToken() - add timestamp token was received;
Before any API call - it should call `_validateToken()` - which does the checks:
if client has no self.token:
use username/pass from config, by calling https://github.com/sdn-sense/sense-o-py-client/blob/master/src/python/sense/client/mainclient.py#L14
if self.token still valid (timestamp check) - return;
if self.token is invalid (expired) - try to do refreshToken() and use refresh_token variable;
if for any reason refreshToken fails - try to get new token with getToken()
if for any reason any API call returns 401 and WWW-Authenticate invalid_token - call _validateToken() - that will get new token. For this one - we will need to have wrapper function of decorator, something like:
Wrapper example:
def exceptionHandler(function):
@wraps(function)
def newFunct(*args, **kwargs):
try:
return function(*args, **kwargs)
except Exception as error:
print(error)
return error.error_code
@exception_handler
def get_driver(uid):
raise Exception('Random Exception Test')
Took another look at the JWT.
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJDc1dzamVkYzZUTmhDdElLWlhvTXBLclRySjhpMktvRWJlTjF3Z1hsbjAwIn0.eyJqdGkiOiI3NzRkMTlmMi01MjgyLTQzNWItOWRjMS00NWFlN2NiMGY5ZjkiLCJleHAiOjE2MTY2OTY4ODAsIm5iZiI6MCwiaWF0IjoxNjE2Njk2NTgwLCJpc3MiOiJodHRwczovL2RldjEudmlybmFvLmNvbTo4NTQzL2F1dGgvcmVhbG1zL1N0YWNrViIsImF1ZCI6WyJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIxZDE4MzU3MC0yNzk4LTRkNjktODBjMy00OTBmOTI2NTk2ZmYiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJTdGFja1YiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiI0YzdkMDZmNC1hY2ZlLTQ4NzItYTFmNy05ZDQ4MDdmYTE2MzQiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIioiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIkZfUHJvZmlsZXMtUiIsIkZfUHJvZmlsZXMtWCIsIkFfQWRtaW4iLCJBX1VzZXIiLCJGX1Byb2ZpbGVzLVciLCJ1bWFfcHJvdGVjdGlvbiIsIkZfVmlzdWFsaXphdGlvbi1SIiwiRl9PcGVyYXRpb25zLU1vZGlmeSIsIkZfS2V5Y2xvYWstUiIsIkZfU2VydmljZXMtRUNDIiwiRl9Ecml2ZXJzLVciLCJjcmVhdGUtcmVhbG0iLCJGX0RyaXZlcnMtWCIsIkZfQUNMLVIiLCJGX1NlcnZpY2VzLVZDTiIsIkZfS2V5Y2xvYWstVyIsIkZfVGlja2V0X1IiLCJvZmZsaW5lX2FjY2VzcyIsIkZfU2VydmljZXMtQUhDIiwiRl9TZXJ2aWNlcy1JQ1ZDIiwidW1hX2F1dGhvcml6YXRpb24iLCJGX0RyaXZlcnMtUiIsIkZfU2VydmljZXMtRE5DIiwiRl9BQ0wtVyJdfSwicmVzb3VyY2VfYWNjZXNzIjp7InJlYWxtLW1hbmFnZW1lbnQiOnsicm9sZXMiOlsidmlldy1pZGVudGl0eS1wcm92aWRlcnMiLCJ2aWV3LXJlYWxtIiwibWFuYWdlLWlkZW50aXR5LXByb3ZpZGVycyIsImltcGVyc29uYXRpb24iLCJyZWFsbS1hZG1pbiIsImNyZWF0ZS1jbGllbnQiLCJtYW5hZ2UtdXNlcnMiLCJxdWVyeS1yZWFsbXMiLCJ2aWV3LWF1dGhvcml6YXRpb24iLCJxdWVyeS1jbGllbnRzIiwicXVlcnktdXNlcnMiLCJtYW5hZ2UtZXZlbnRzIiwibWFuYWdlLXJlYWxtIiwidmlldy1ldmVudHMiLCJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwibWFuYWdlLWF1dGhvcml6YXRpb24iLCJtYW5hZ2UtY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyJdfSwiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiQWRtaW4gS2V5Y2xvYWsiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiIsImdpdmVuX25hbWUiOiJBZG1pbiIsImZhbWlseV9uYW1lIjoiS2V5Y2xvYWsiLCJlbWFpbCI6ImFsYmVydG8uZXN0LmppbWVuZXpAZ21haWwuY29tIn0.lG725GohtzsnRRBRA-S2zi5CBcuhx6Ovg-NLQgCv3E4PCR4BwsziPZiJC7g--DbRblyuHOXhdBaF5ULEf6-5yhnl6jY3n5IDKBL0cTYvV-HREcyuIS2DpB1Ik8Y1YpbHNzF9VNxYoz72T0jLOhNI3BgtsXnHLrVAL_sih0wJ6NHuT0u37cxeyRz7rf5-PB7AS8XLg-lx_DXU3-yyYISK_UR9oJAGIR7CrSIPwB4ek7qCLhjVV1qMMSxbrQlPomaYz9r9V1CbwVJmLNy9RV4LVHgT0AiJhs0SI-lsSqxcsOSPUjSaryx642MDKKVPdL1tOr2EjPp3zYi17DAX7VFYGQ",
"expires_in": 300,
"refresh_expires_in": 1800,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIwODU4ZGNhMi1jNzIwLTQ1ZjEtYjRjNC1jMTY3Njk0ZmQ0ZjEifQ.eyJqdGkiOiI3NTFmMGU3ZS02NGIyLTRlZDQtYmYyMy01Nzg4YjU1ODRkNDkiLCJleHAiOjE2MTY2OTgzODAsIm5iZiI6MCwiaWF0IjoxNjE2Njk2NTgwLCJpc3MiOiJodHRwczovL2RldjEudmlybmFvLmNvbTo4NTQzL2F1dGgvcmVhbG1zL1N0YWNrViIsImF1ZCI6Imh0dHBzOi8vZGV2MS52aXJuYW8uY29tOjg1NDMvYXV0aC9yZWFsbXMvU3RhY2tWIiwic3ViIjoiMWQxODM1NzAtMjc5OC00ZDY5LTgwYzMtNDkwZjkyNjU5NmZmIiwidHlwIjoiUmVmcmVzaCIsImF6cCI6IlN0YWNrViIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjRjN2QwNmY0LWFjZmUtNDg3Mi1hMWY3LTlkNDgwN2ZhMTYzNCIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJGX1Byb2ZpbGVzLVIiLCJGX1Byb2ZpbGVzLVgiLCJBX0FkbWluIiwiQV9Vc2VyIiwiRl9Qcm9maWxlcy1XIiwidW1hX3Byb3RlY3Rpb24iLCJGX1Zpc3VhbGl6YXRpb24tUiIsIkZfT3BlcmF0aW9ucy1Nb2RpZnkiLCJGX0tleWNsb2FrLVIiLCJGX1NlcnZpY2VzLUVDQyIsIkZfRHJpdmVycy1XIiwiY3JlYXRlLXJlYWxtIiwiRl9Ecml2ZXJzLVgiLCJGX0FDTC1SIiwiRl9TZXJ2aWNlcy1WQ04iLCJGX0tleWNsb2FrLVciLCJGX1RpY2tldF9SIiwib2ZmbGluZV9hY2Nlc3MiLCJGX1NlcnZpY2VzLUFIQyIsIkZfU2VydmljZXMtSUNWQyIsInVtYV9hdXRob3JpemF0aW9uIiwiRl9Ecml2ZXJzLVIiLCJGX1NlcnZpY2VzLUROQyIsIkZfQUNMLVciXX0sInJlc291cmNlX2FjY2VzcyI6eyJyZWFsbS1tYW5hZ2VtZW50Ijp7InJvbGVzIjpbInZpZXctaWRlbnRpdHktcHJvdmlkZXJzIiwidmlldy1yZWFsbSIsIm1hbmFnZS1pZGVudGl0eS1wcm92aWRlcnMiLCJpbXBlcnNvbmF0aW9uIiwicmVhbG0tYWRtaW4iLCJjcmVhdGUtY2xpZW50IiwibWFuYWdlLXVzZXJzIiwicXVlcnktcmVhbG1zIiwidmlldy1hdXRob3JpemF0aW9uIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LXVzZXJzIiwibWFuYWdlLWV2ZW50cyIsIm1hbmFnZS1yZWFsbSIsInZpZXctZXZlbnRzIiwidmlldy11c2VycyIsInZpZXctY2xpZW50cyIsIm1hbmFnZS1hdXRob3JpemF0aW9uIiwibWFuYWdlLWNsaWVudHMiLCJxdWVyeS1ncm91cHMiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoiZW1haWwgcHJvZmlsZSJ9.sLpaSfA-Xwg56sMdQMujf_LwSVuxYMhZmqMvASGUwOA",
"token_type": "bearer",
"not-before-policy": 1590423183,
"session_state": "4c7d06f4-acfe-4872-a1f7-9d4807fa1634",
"scope": "email profile"
}
not-before-policy
is a Keycloak proprietary attribute. We can ignore it.expires_in
or refresh_expires_in` attribute. {
"error": "invalid_grant",
"error_description": "Refresh token expired"
}
So the flow in here https://github.com/sdn-sense/sense-o-py-client/issues/8#issuecomment-802890678 still applies.
I pushed two utility commands token-access.sh and token-refresh.sh in StackV.devops/testing/scripts to help working with the tokens from command line.
@scaly789 The revised tasks are below.
workflow_combined
client class. How do I import the classes from the other files? As of right now, I keep getting this error.
ehgan@DESKTOP-GA2U80D:/mnt/c/Users/gan67/Desktop/sense-o-py-client/src/python/sense/client$ python test_service.py
Traceback (most recent call last):
File "test_service.py", line 4, in
@scaly789
Two items for the next task:
/sense/service/*
endpoints and converged to /instance/*
endpoints. workflow_combined
group. I will provide some more instructions on the workflow. Post request is outputting an error shown below:
{"exception":"Unrecognized token 'alias': was expecting ('true', 'false' or 'null')\n at [Source: (io.undertow.servlet.spec.ServletInputStreamImpl); line: 1, column: 7]","stacktrace":"com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'alias': was expecting ('true', 'false' or 'null')\n at [Source: (io.undertow.servlet.spec.ServletInputStreamImpl); line: 1, column: 7]\n\tat com.fasterxml.jackson.core.jackson-core@2.9.10\/\/com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1804)\n\tat com.fasterxml.jackson.core.jackson-core@2.9.10\/\/com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:703)\n\tat com.fasterxml.jackson.core.jackson-core@2.9.10\/\/com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidToken(UTF8StreamJsonParser.java:3532)\n\tat com.fasterxml.jackson.core.jackson-core@2.9.10\/\/com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2627)\n\tat com.fasterxml.jackson.core.jackson-core@2.9.10\/\/com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextTokenNotInObject(UTF8StreamJsonParser.java:832)\n\tat com.fasterxml.jackson.core.jackson-core@2.9.10\/\/com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:729)\n\tat org.jboss.resteasy.resteasy-jackson2-provider@3.9.1.Final\/\/org.jboss.resteasy.plugins.providers.jackson.ResteasyJackson2Provider.readFrom(ResteasyJackson2Provider.java:168)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.readFrom(AbstractReaderInterceptorContext.java:66)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.interception.ServerReaderInterceptorContext.readFrom(ServerReaderInterceptorContext.java:61)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:56)\n\tat org.jboss.resteasy.resteasy-crypto@3.9.1.Final\/\/org.jboss.resteasy.security.doseta.DigitalVerificationInterceptor.aroundReadFrom(DigitalVerificationInterceptor.java:36)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:59)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.plugins.interceptors.encoding.GZIPDecodingInterceptor.aroundReadFrom(GZIPDecodingInterceptor.java:123)\n\tat deployment.StackV-ear-1.0-SNAPSHOT.ear\/\/org.jboss.resteasy.plugins.interceptors.encoding.GZIPDecodingInterceptor$Proxy$$$_WeldClientProxy.aroundReadFrom(Unknown Source)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:59)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.MessageBodyParameterInjector.inject(MessageBodyParameterInjector.java:198)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.MethodInjectorImpl.injectArguments(MethodInjectorImpl.java:91)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:113)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:517)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:406)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$0(ResourceMethodInvoker.java:370)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:356)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:372)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:344)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:317)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:440)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:229)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:135)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:356)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:138)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:215)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:227)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)\n\tat org.jboss.resteasy.resteasy-jaxrs@3.9.1.Final\/\/org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)\n\tat javax.servlet.api@2.0.0.Final\/\/javax.servlet.http.HttpServlet.service(HttpServlet.java:590)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)\n\tat io.undertow.websocket@2.0.27.Final\/\/io.undertow.websockets.jsr.JsrWebSocketFilter.doFilter(JsrWebSocketFilter.java:173)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)\n\tat io.opentracing.contrib.opentracing-jaxrs2\/\/io.opentracing.contrib.jaxrs2.server.SpanFinishingFilter.doFilter(SpanFinishingFilter.java:52)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)\n\tat deployment.StackV-ear-1.0-SNAPSHOT.ear.StackV-web-1.0-SNAPSHOT.war\/\/com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:209)\n\tat deployment.StackV-ear-1.0-SNAPSHOT.ear.StackV-web-1.0-SNAPSHOT.war\/\/com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:244)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)\n\tat org.wildfly.security.elytron-web.undertow-server@1.6.0.Final\/\/org.wildfly.elytron.web.undertow.server.ElytronRunAsHandler.lambda$handleRequest$1(ElytronRunAsHandler.java:68)\n\tat org.wildfly.security.elytron-private@1.10.4.Final\/\/org.wildfly.security.auth.server.FlexibleIdentityAssociation.runAsFunctionEx(FlexibleIdentityAssociation.java:103)\n\tat org.wildfly.security.elytron-private@1.10.4.Final\/\/org.wildfly.security.auth.server.Scoped.runAsFunctionEx(Scoped.java:161)\n\tat org.wildfly.security.elytron-private@1.10.4.Final\/\/org.wildfly.security.auth.server.Scoped.runAs(Scoped.java:73)\n\tat org.wildfly.security.elytron-web.undertow-server@1.6.0.Final\/\/org.wildfly.elytron.web.undertow.server.ElytronRunAsHandler.handleRequest(ElytronRunAsHandler.java:67)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)\n\tat io.undertow.core@2.0.27.Final\/\/io.undertow.server.handlers.DisableCacheHandler.handleRequest(DisableCacheHandler.java:33)\n\tat io.undertow.core@2.0.27.Final\/\/io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)\n\tat io.undertow.core@2.0.27.Final\/\/io.undertow.security.handlers.AuthenticationConstraintHandler.handleRequest(AuthenticationConstraintHandler.java:53)\n\tat io.undertow.core@2.0.27.Final\/\/io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler.handleRequest(ServletSecurityConstraintHandler.java:59)\n\tat io.undertow.core@2.0.27.Final\/\/io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)\n\tat org.wildfly.security.elytron-web.undertow-server-servlet@1.6.0.Final\/\/org.wildfly.elytron.web.undertow.server.servlet.CleanUpHandler.handleRequest(CleanUpHandler.java:38)\n\tat io.undertow.core@2.0.27.Final\/\/io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)\n\tat org.wildfly.extension.undertow@18.0.1.Final\/\/org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)\n\tat io.undertow.core@2.0.27.Final\/\/io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)\n\tat org.wildfly.extension.undertow@18.0.1.Final\/\/org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)\n\tat org.keycloak.keycloak-wildfly-elytron-oidc-adapter@8.0.1\/\/org.keycloak.adapters.elytron.KeycloakServletExtension.lambda$null$0(KeycloakServletExtension.java:39)\n\tat io.undertow.core@2.0.27.Final\/\/io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)\n\tat org.wildfly.extension.undertow@18.0.1.Final\/\/org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)\n\tat org.wildfly.extension.undertow@18.0.1.Final\/\/org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)\n\tat org.wildfly.extension.undertow@18.0.1.Final\/\/org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)\n\tat org.wildfly.extension.undertow@18.0.1.Final\/\/org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)\n\tat org.wildfly.extension.undertow@18.0.1.Final\/\/org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78)\n\tat io.undertow.servlet@2.0.27.Final\/\/io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99)\n\tat io.undertow.core@2.0.27.Final\/\/io.undertow.server.Connectors.executeRootHandler(Connectors.java:376)\n\tat io.undertow.core@2.0.27.Final\/\/io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)\n\tat org.jboss.threads@2.3.3.Final\/\/org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)\n\tat org.jboss.threads@2.3.3.Final\/\/org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)\n\tat org.jboss.threads@2.3.3.Final\/\/org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)\n\tat org.jboss.threads@2.3.3.Final\/\/org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)\n\tat java.base\/java.lang.Thread.run(Thread.java:834)\n","cause":null,"type":"com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'alias': was expecting ('true', 'false' or 'null')\n at [Source: (io.undertow.servlet.spec.ServletInputStreamImpl); line: 1, column: 7]"}
I think that the issue might be because my code is using the intent json and creating a dictionary with values of type unicode instead of type string, but I'm not quire sure. The wiki page on how to run tests with my code is https://github.com/sdn-sense/sense-o-py-client/wiki
@scaly789 See Alberto's comment here: https://github.com/esnet/StackV/issues/1020#issuecomment-844476566
Let's try it again after he fixes the dev1 deployment.
POST methods fixed.
I have also moved the test script. Will close this issue and restructure the codes (including unit tests) in another issue.
The SENSE client framework maps into the following code structure:
The phase-I work will be on
auth
,intent
andservice
to replicate the functionality of sense-o client BASH shell scripts under StackV.devops.One example of similar work is the NSF gene-tools: https://github.com/GENI-NSF/geni-tools/tree/develop/src/gcf
https://github.com/GENI-NSF/geni-tools/wiki/Omni
A How-To Wiki for GENI omni client: https://groups.geni.net/geni/wiki/HowToUseOmni