# -*- coding: utf-8 -*- from __future__ import absolute_import try: import cherrypy HAS_CHERRYPY = True except ImportError: HAS_CHERRYPY = False import os import salt.config from tests.support.mock import patch from tests.support.paths import TMP_CONF_DIR if HAS_CHERRYPY: from tests.support.cptestcase import BaseCherryPyTestCase from salt.netapi.rest_cherrypy import app else: from tests.support.unit import TestCase, skipIf @skipIf(HAS_CHERRYPY is False, 'The CherryPy python package needs to be installed') class BaseCherryPyTestCase(TestCase): pass class BaseToolsTest(BaseCherryPyTestCase): pass class BaseRestCherryPyTest(BaseCherryPyTestCase): ''' A base TestCase subclass for the rest_cherrypy module This mocks all interactions with Salt-core and sets up a dummy (unsubscribed) CherryPy web server. ''' def __get_opts__(self): return None @classmethod def setUpClass(cls): master_conf = os.path.join(TMP_CONF_DIR, 'master') cls.config = salt.config.client_config(master_conf) cls.base_opts = {} cls.base_opts.update(cls.config) @classmethod def tearDownClass(cls): del cls.config del cls.base_opts def setUp(self): # Make a local reference to the CherryPy app so we can mock attributes. self.app = app self.addCleanup(delattr, self, 'app') master_conf = os.path.join(TMP_CONF_DIR, 'master') client_config = salt.config.client_config(master_conf) base_opts = {} base_opts.update(client_config) base_opts.update(self.__get_opts__() or { 'external_auth': { 'auto': { 'saltdev': [ '@wheel', '@runner', '.*', ], }, 'pam': { 'saltdev': [ '@wheel', '@runner', '.*', ], } }, 'rest_cherrypy': { 'port': 8000, 'debug': True, }, }) root, apiopts, conf = app.get_app(base_opts) cherrypy.tree.mount(root, '/', conf) cherrypy.server.unsubscribe() cherrypy.engine.start() # Make sure cherrypy does not memleak on it's bus since it keeps # adding handlers without cleaning the old ones each time we setup # a new application for value in cherrypy.engine.listeners.values(): value.clear() cherrypy.engine._priorities.clear() self.addCleanup(cherrypy.engine.exit) class Root(object): ''' The simplest CherryPy app needed to test individual tools ''' exposed = True _cp_config = {} def GET(self): return {'return': ['Hello world.']} def POST(self, *args, **kwargs): return {'return': [{'args': args}, {'kwargs': kwargs}]} if HAS_CHERRYPY: class BaseToolsTest(BaseCherryPyTestCase): # pylint: disable=E0102 ''' A base class so tests can selectively turn individual tools on for testing ''' def __get_conf__(self): return { '/': { 'request.dispatch': cherrypy.dispatch.MethodDispatcher(), }, } def __get_cp_config__(self): return {} def setUp(self): root = Root() patcher = patch.object(root, '_cp_config', self.__get_cp_config__()) patcher.start() self.addCleanup(patcher.stop) # Make sure cherrypy does not memleak on it's bus since it keeps # adding handlers without cleaning the old ones each time we setup # a new application for value in cherrypy.engine.listeners.values(): value.clear() cherrypy.engine._priorities.clear() app = cherrypy.tree.mount(root, '/', self.__get_conf__()) cherrypy.server.unsubscribe() cherrypy.engine.start() self.addCleanup(cherrypy.engine.exit)