sdn-sense / sense-o-py-client

Other
0 stars 3 forks source link

SENSE client framework python code structure (phase-I) #8

Closed xi-yang closed 3 years ago

xi-yang commented 3 years ago

The SENSE client framework maps into the following code structure:

/sense
        /auth               # credential and API client authentication  
        /intent             # intent (service profile) composing, validation and negotiation - data model and API methods
        /lookup             # methods to call SENSE-O discovery API
        /service            # methods to call SENSE-O service API for service creation and life-cycle management
        /subscribe          # (future) for pub/sub async interaction with SENSE-O 
        /ansible            # (future) Ansible role module 
        /apps               # (future) placeholder for composite methods in support of application workflows
        /test               # shell scripts for testing

The phase-I work will be on auth, intent and service 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

xi-yang commented 3 years ago

Sprint 1 (March 1st - March 14th):

Sprint 2 (March 15th - March 28th):

xi-yang commented 3 years ago

@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.

scaly789 commented 3 years ago

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

xi-yang commented 3 years ago

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.

xi-yang commented 3 years ago

@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.

xi-yang commented 3 years ago

@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.

xi-yang commented 3 years ago

@juztas The above is FYI so that you can see the progress on the client package.

juztas commented 3 years ago

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.

xi-yang commented 3 years ago

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.

xi-yang commented 3 years ago

@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.

xi-yang commented 3 years ago

@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).

juztas commented 3 years ago

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')
xi-yang commented 3 years ago

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"
}

So the flow in here https://github.com/sdn-sense/sense-o-py-client/issues/8#issuecomment-802890678 still applies.

xi-yang commented 3 years ago

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.

xi-yang commented 3 years ago

@scaly789 The revised tasks are below.

scaly789 commented 3 years ago

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 from sense.client.api.workflow_combined_api import WorkflowCombinedApi ImportError: No module named sense.client.api.workflow_combined_api 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 from sense.client.requestwrapper import RequestWrapper ImportError: No module named sense.client.requestwrapper 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 from sense.client.requestwrapper import RequestWrapper ImportError: No module named sense.client.requestwrapper 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 from sense.client.requestwrapper import RequestWrapper ImportError: No module named sense.client.requestwrapper 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 from sense.client.mainclient import MainClient ImportError: No module named sense.client.mainclient ehgan@DESKTOP-GA2U80D:/mnt/c/Users/gan67/Desktop/sense-o-py-client/src/python/sense/client$

xi-yang commented 3 years ago

@scaly789

Two items for the next task:

scaly789 commented 3 years ago

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

xi-yang commented 3 years ago

@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.

xi-yang commented 3 years ago

POST methods fixed.

I have also moved the test script. Will close this issue and restructure the codes (including unit tests) in another issue.