Source code for dcos_test_utils.enterprise
""" This module defines an DcosApiSession child class for using Mesosphere Enterprise DC/OS
"""
import logging
import os
from dcos_test_utils import dcos_api, helpers, iam
log = logging.getLogger(__name__)
[docs]class MesosNodeClientMixin:
""" This Mixin allows any request to be made against a master or agent
mesos HTTP port by providing the keyword 'mesos_node'. Thus, the user
does not have to specify the master/agent port or which arbitrary host
in the cluster meeting that role
"""
[docs] def api_request(self, method, path_extension, *, scheme=None, host=None, query=None,
fragment=None, port=None, mesos_node=None, **kwargs):
""" This mixin method provides an additional keyword for easily directing to
Mesos endpoints on either masters or slaves
:param mesos_node: IP string of either a master or slave in the cluster
:type mesos_node: str
:returns: API response
:rtype: requests.Response
"""
if mesos_node is not None:
assert port is None, 'Usage error: mesos_node keyword will set port'
assert host is None, 'Usage error: mesos_node keyword will set host'
if mesos_node == 'master':
port = 5050
host = self.masters[0]
elif mesos_node == 'agent':
port = 5051
host = self.slaves[0]
else:
raise AssertionError('Mesos node type not recognized: {}'.format(mesos_node))
return super().api_request(method, path_extension, scheme=scheme, host=host, query=query,
fragment=fragment, port=port, **kwargs)
[docs]class EnterpriseUser(dcos_api.DcosUser):
""" Enterprise user abstraction for authenticating the EnterpriseApiSession client
:param uid: username to log in with
:type uid: str
:param password: password to be used with uid
:type password: str
"""
def __init__(self, uid: str, password: str):
self.uid = uid
self.password = password
super().__init__(self.auth_json)
@property
def auth_json(self):
""" Property for the headers needed to log into an Enterprise Edition cluster"""
return {'uid': self.uid, 'password': self.password}
[docs]class EnterpriseApiSession(MesosNodeClientMixin, dcos_api.DcosApiSession):
""" DcosApiSession specialized for use with an Enterprise cluster
Note:
This class is **required** for Enterprise API interaction
:param ssl_enabled: if the security parameter is configured to permissive or strict, this should be True
:type ssl_enabled: bool
"""
def __init__(self, *args, ssl_enabled=True, **kwargs):
super().__init__(*args, **kwargs)
self.ssl_enabled = ssl_enabled
[docs] @classmethod
def create(cls):
""" Uses the method :func:`EnterpriseApiSession.get_args_from_env` to create an EnterpriseApiSession
"""
api = cls(**cls.get_args_from_env())
if api.ssl_enabled:
api.set_ca_cert()
api.login_default_user()
api.set_initial_resource_ids()
return api
@property
def iam(self):
""" Property which generates a new client for :class:`~dcos_test_utils.iam.Iam`
"""
return iam.Iam(self.default_url.copy(path='acs/api/v1'), session=self.copy().session)
@property
def secrets(self):
""" Property which generates a new client where all paths are prepended with /secrets/v1
"""
new = self.copy()
new.default_url = self.default_url.copy(path='secrets/v1')
return new
@property
def ca(self):
""" Property which generates a new client where all paths are prepended with /ca/api/v2
"""
new = self.copy()
new.default_url = self.default_url.copy(path='ca/api/v2')
return new
[docs] @staticmethod
def get_args_from_env():
""" Uses all parameters defined in :func:`~dcos_test_utils.dcos_api.DcosApiSession.get_args_from_env`
and adds some additional environment variables:
* **DCOS_LOGIN_UNAME** username to user for DC/OS login
* **DCOS_LOGIN_PW** password to user for DC/OS login
* **DCOS_SSL_ENABLED** can be 'true' or 'false'. Set to false only if security is configured as disabled
"""
assert 'DCOS_LOGIN_UNAME' in os.environ, 'DCOS_LOGIN_UNAME must be set to login!'
assert 'DCOS_LOGIN_PW' in os.environ, 'DCOS_LOGIN_PW must be set!'
uid = os.environ['DCOS_LOGIN_UNAME']
password = os.environ['DCOS_LOGIN_PW']
args = dcos_api.DcosApiSession.get_args_from_env()
args['auth_user'] = EnterpriseUser(uid, password)
args['ssl_enabled'] = os.getenv('DCOS_SSL_ENABLED', 'true') == 'true'
return args
[docs] def set_ca_cert(self):
""" If security is permissive or strict, and the API session is not configured with verify=False,
then the custom CA cert for the desired cluster must be attached to the session, which this method will do
"""
log.info('Attempt to get CA bundle via Admin Router')
r = self.get('/ca/dcos-ca.crt', verify=False)
r.raise_for_status()
self.session.verify = helpers.session_tempfile(r.content)
[docs] def set_initial_resource_ids(self):
""" helper method for setting the `initial_resource_ids` property of this ApiSession object
This is useful for resetting the RIDs that were added over the couse of interaction with the cluster
"""
self.initial_resource_ids = []
r = self.iam.get('/acls')
r.raise_for_status()
for o in r.json()['array']:
self.initial_resource_ids.append(o['rid'])
[docs] def wait_for_dcos(self):
""" This method will wait for basic DC/OS services to be running. Once basic endpoints are up,
this method will set the custom CA cert and authenticate with the cluster
"""
if self.ssl_enabled:
self.set_ca_cert()
super().wait_for_dcos()
self.set_initial_resource_ids()