nuagenetworks / vspk-python

A Python library for managing Nuage through its API
http://www.nuagenetworks.net
BSD 3-Clause "New" or "Revised" License
17 stars 19 forks source link

http headers incorrect after starting a second VSD session #41

Closed marcowenwolf closed 4 years ago

marcowenwolf commented 4 years ago

Problem description

Test automation requires the capability to define VSD session per enterprise to provide access to enterprises during test runs. It should be possible to perform CRUD actions on multiple enterprises over time.

Reproduction

This result into a None object for first child. It looks like the HTTP header is garbeld with nume2 headers. This is clearly visible using robot framework output:

See log.html session1: Return: <vspk.v6.nume.NUMe object at 0x7f0a64646208> session2: Return: <vspk.v6.nume.NUMe object at 0x7f0a67fb4fd0>

Next the call to session1 to get enterprise by name from NUME object 0x7f0a64646208 (loggin session to se1-c1-v1 enterprise). From below excerpt you can see that the http header uses the wrong X-Nuage-Organization': 'se1-c5-v1' header. If the second session is not started, this test is successful.

``` Get the first child of a given kind Start / End / Elapsed: 20200806 22:13:59.973 / 20200806 22:14:00.163 / 00:00:00.190 22:13:59.974 TRACE Arguments: [ obj= | attr='enterprises' | fltr='name is "se1-c1-v1"' ] 22:13:59.975 INFO > GET https://124.252.253.200:8443/nuage/api/v6/enterprises 22:13:59.975 DEBUG > headers: {'Content-Type': 'application/json', 'X-Nuage-Filter': 'name is "se1-c1-v1"', 'X-Nuage-Page': '0', 'X-Nuage-PageSize': '1', 'X-Nuage-Organization': 'se1-c5-v1', 'Authorization': 'XREST bWFyY3dvbGY6YzY2ZmRmM2ItMDVjZS00ZTA4LTlmOGMtMjQzYWU0MTQ5MGVj'} 22:13:59.976 DEBUG > data: null 22:14:00.159 DEBUG https://124.252.253.200:8443 "GET /nuage/api/v6/enterprises HTTP/1.1" 200 0 22:14:00.161 INFO < GET https://124.252.253.200:8443/nuage/api/v6/enterprises [200] 22:14:00.161 DEBUG < headers: {'Server': 'Apache-Coyote/1.1', 'Pragma': 'No-cache', 'Cache-Control': 'no-cache', 'Expires': 'Wed, 31 Dec 1969 16:00:00 PST', 'Set-Cookie': 'rememberMe=deleteMe; Path=/nuage; Max-Age=0; Expires=Wed, 05-Aug-2020 20:14:01 GMT', 'X-Nuage-FilterType': 'none', 'X-Frame-Options': 'deny', 'X-Nuage-PageSize': '1', 'X-Nuage-Count': '0', 'Strict-Transport-Security': 'max-age=31536000', 'Access-Control-Expose-Headers': 'X-Nuage-Organization, X-Nuage-ProxyUser, X-Nuage-OrderBy, X-Nuage-FilterType, X-Nuage-Filter, X-Nuage-Page, X-Nuage-PageSize, X-Nuage-Count, X-Nuage-Custom, X-Nuage-ClientType, X-SSL-Client-CN, X-SSL-Client-ORG, X-SSL-Client-UID, X-SSL-Issuer-CN, X-SSL-Client-DN, X-SSL-Issuer-DN', 'X-Nuage-Filter': 'name is "se1-c1-v1"', 'Access-Control-Allow-Origin': '*', 'X-Nuage-OrderBy': 'name ASC', 'Content-Security-Policy': 'default-src', 'X-Nuage-Page': '0', 'X-XSS-Protection': '1', 'X-Content-Type-Options': 'nosniff', 'Referrer-Policy': 'origin', 'Content-Length': '0', 'Date': 'Thu, 06 Aug 2020 20:14:00 GMT'} 22:14:00.162 DEBUG < data: null 22:14:00.162 TRACE Return: None ```

Attached:

test_vsd.py.txt log.html.txt bug.robot.txt

Run Python script:

(nuage-cats-6.0.5) marcwolf@laptop:~/tmp> pytest --disable-warnings --verbose test_vsd.py 
==================================================== test session starts ====================================================
platform linux -- Python 3.6.10, pytest-6.0.1, py-1.9.0, pluggy-0.13.1 -- /home/marcwolf/venvs/nuage-cats-6.0.5/bin/python3
cachedir: .pytest_cache
rootdir: /home/marcwolf/tmp
collected 2 items                                                                                                           

test_vsd.py::test_get_first_child PASSED                                                                              [ 50%]
test_vsd.py::test_get_first_child_after_next_session FAILED                                                           [100%]

========================================================= FAILURES ==========================================================
__________________________________________ test_get_first_child_after_next_session __________________________________________

    def test_get_first_child_after_next_session():
        my_session1 = myVSD.start_vsd_session(url='https://124.252.253.200:8443',
                                         enterprise='se1-c1-v1',
                                         username='xxxxxxxxxxx',
                                         password='xxxxxxxxxxx')
        my_session2 = myVSD.start_vsd_session(url='https://124.252.253.200:8443',
                                         enterprise='se1-c5-v1',
                                         username='xxxxxxxxxx',
                                         password='xxxxxxxxxx')
        assert my_session1 is not None
        assert my_session2 is not None
        my_enterprise1 = myVSD.get_first_child(obj=my_session1, attr='enterprises', fltr='name is "se1-c1-v1"')
>       assert my_enterprise1.name == 'se1-c1-v1'
E       AttributeError: 'NoneType' object has no attribute 'name'

test_vsd.py:79: AttributeError
----------------------------------------------------- Captured log call -----------------------------------------------------
DEBUG    vsdlib:test_vsd.py:22 > VSDLib: Start VSD Session using url: https://124.252.253.200:8443
DEBUG    vsdlib:test_vsd.py:25 < VSDLib: Started VSD Session: <vspk.v6.nuvsdsession.NUVSDSession object at 0x7ff214e7c630>
DEBUG    vsdlib:test_vsd.py:22 > VSDLib: Start VSD Session using url: https://124.252.253.200:8443
DEBUG    vsdlib:test_vsd.py:25 < VSDLib: Started VSD Session: <vspk.v6.nuvsdsession.NUVSDSession object at 0x7ff214e7cb00>
================================================== short test summary info ==================================================
FAILED test_vsd.py::test_get_first_child_after_next_session - AttributeError: 'NoneType' object has no attribute 'name'

========================================== 1 failed, 1 passed, 3 warnings in 2.78s ==========================================
pdellaert commented 4 years ago

Hi @marcowenwolf,

Here's an example on how to use multiple sessions within the same script: https://github.com/nuagenetworks/vspk-examples/blob/master/python/multi-vsd_list_enterprises_domains_vms_structure_acls.py This example uses different VSDs, but it is the same process for a single VSD environment, but have multiple users.

You need to use the python with statement (https://docs.python.org/3/reference/compound_stmts.html#the-with-statement) for this functionality.

I hope that helps.

marcowenwolf commented 4 years ago

Hallo Phillipe,

Thanks for the quick response. The 'with' suggestion works as a charm. So it looks like you can pass on the session object correctly, but using the session.user object causes issues re-using fetchers in case of multiple VSD sessions. For me it makes sense to use session object to pass on with 'with' statement.

class VSDLib:
    def start_vsd_session(self, url, username='csproot', password='csproot', enterprise='csp'):
        logger.debug('> VSDLib: Start VSD Session using url: {}'.format(url))
        nc = vsdk.NUVSDSession(username=username, password=password, enterprise=enterprise, api_url=url)
        session = nc.start()
        logger.debug('< VSDLib: Started VSD Session: {}'.format(session))
        return session

    def get_first_child(self, obj, attr, fltr=''):
        """Get the first child of a given kind

        Arguments:
        - obj -- the parent object
        - attr -- the attribute name of the child type list
        - fltr -- search filter

        Returns:
        - child object or None

        Examples:
        | ${r} = | Get First Child |  obj=root | attr=enterprises | fltr=name is "sdnlight-t1" |
        """
        with obj:
            logger.debug('< get_first_child: {}, {}, {}'.format(obj, attr, fltr))
            fetcher = obj.user.__dict__[attr]
            child = fetcher.get_first(filter=fltr)
            logger.debug('< Child: {}'.format(child))
            return child