Session
: Unravelling a mysterious object (Part1)
Okay, so today I'm going to tell you a little story through code.
This is a partial story about session
and my encounters with this mysterious entity. Bear with me, it's going to be a ride (probably a trippy one).
Prerequisite knowledge: – Python (intro level), – HTTP request methods
I first encountered this object, not just under that generic name, but as a mysterious entity that did other things. Those who received this session
, said it was of a particular type (or kind) ~keystoneauth1.adapter.Adapter
That description seemed just as cryptic. But it did give a hint.
Here's a sample of our first meet.
#location: openstacksdk/openstack/baremetal/v1/node.py - Node/
def commit(self, session, *args, **kwargs):
"""Commit the state of the instance to the remote resource.
:param session: The session to use for making this request.
:type session: :class:`~keystoneauth1.adapter.Adapter`
:return: This :class:`Node` instance.
"""
Hmm. Now what did that tell me?
That there is this function called commit
. And it receives this session
gladly as a parameter (required it, in fact). commit
says session
is of some particular type.
Now, I had not encountered this type before. But from the name I figured this session
was someone that authenticated you and then allowed you to do things with it. Sort of like a magic wand. Perhaps it first identifies you, and then it can be used to make this happen, make others (maybe a server) do things for you. Also, just like a wand, it can be passed around. So it must have some memory or state of who or how it was charmed. This is all just guess work though, from what we see here.
With not much of a prior introduction to it and not knowing where it came from, I wandered around this place that is the openstacksdk
trying to find more about it. You see, I was supposed to implement a feature at this place and to do so, I needed to use this session
to get some things done. I wanted to get to know all about this session first Who it was, what does it do. But alas, my search failed. I didn't find a more detailed description nearby. Tracing back, following it, through the signs it left, I saw it invoked like this.
from keystoneauth1 import adapter
from keystoneauth1 import session as ks_session
It was always summoned, not a native of this place (openstacksdk
) but brought in from outside. So I didn't find anyone having detailed information about this session. It was one mysterious keystone. I was dismayed, I had to use it. How would I, if I didn't know who it was, or know how to talk to it?
I was saddened, I was stuck. I was scared of not progressing, and almost fell into a rut.
My mentor fortunately noticed, and helped me out, they pointed me at examples, encouraging me, to figure it out.
Here is one such example
def list_vifs(self, session):
"""List IDs of VIFs attached to the node.
The exact form of the VIF ID depends on the network interface used by
the node. In the most common case it is a Network service port
(NOT a Bare Metal port) ID.
:param session: The session to use for making this request.
:type session: :class:`~keystoneauth1.adapter.Adapter`
:return: List of VIF IDs as strings.
:raises: :exc:`~openstack.exceptions.NotSupported` if the server
does not support the VIF API.
"""
session = self._get_session(session)
version = self._assert_microversion_for(
session, 'fetch', _common.VIF_VERSION,
error_message=("Cannot use VIF attachment API"))
request = self._prepare_request(requires_id=True)
request.url = utils.urljoin(request.url, 'vifs')
response = session.get(
request.url, headers=request.headers, microversion=version)
msg = ("Failed to list VIFs attached to bare metal node {node}"
.format(node=self.id))
exceptions.raise_from_response(response, error_message=msg)
return [vif['id'] for vif in response.json()['vifs']]
Looking close, ignoring the rest, we can focus on the session object and see how it behaves, try to glean how it's used.
session = self._get_session(session)
# Just by looking we can guess, perhaps this session is being refreshed to it's current state, or perhaps minorly transformed from a generic form into a form we can use.
# And indeed looking at it's source, indicates the latter
response = session.get(
request.url, headers=request.headers, microversion=version)
# Ignore the microversion for now. But if you know basic http, looks like what's happening is a get request is being initiated at the url, and the returned response is being saved.
# For some magicians it would be natural to just wave this s̶p̶e̶l̶l̶ fuction of session at any url and hope it works.
# Some even more daring would probably even try `session.put( ... ) ` or session.delete( ... ) and expect it to work*.
# Some would be too distracted by this strange microversion and hesitate to touch the function until they know more, fearing side effects. (like I was at first :p)
# * (GET, PUT, POST, DELETE being some classic HTTP request methods)
Browsing through the code, I did find some other incantations. Like:
response = session.put(
request.url, json=body,
headers=request.headers, microversion=version,
retriable_status_codes=_common.RETRIABLE_STATUS_CODES)
response = session.post(
request.url, json=body,
headers=request.headers, microversion=version,
retriable_status_codes=retriable_status_codes)
response = session.delete(
request.url, headers=request.headers, microversion=version,
retriable_status_codes=_common.RETRIABLE_STATUS_CODES)
I tried these incantations myself (skipping the extra parameters). And it did seem to work.
So it does seem like an interface to HTTP methods. This session
wand allows you to call HTTP methods. You can pass it the url, headers and json body in case of post/put request and it seemingly does the job. How it works is magic (a black box). What else it does, is also a mystery.
For my purpose, this was all I needed from our mysterious session
.
And so we parted ways. Until we met again, another place.
I hadn't seen fine details of our
session
. Didn't know where exactly they were from. Hadn't seen howsession
was created, haven't read about their usage or detailed description in a document. And that felt blinding.But, just by observing someone's behaviour, seeing how others call them, how they react to those calls, you can sometimes glean enough about an entity (Perhaps even a person).. Enough to work with them.
Who they are may remain a mystery, and you may never get to know, as much as you'd like. But's that's okay. You don't have to always.