def test():

    p = list_path(".")

    assert p is not None
    assert isinstance(p, list)
    assert len(p) > 0

    try:
        list_path("blabla")
    except FileNotFoundError:
        pass
    else:
        pytest.fail("This call should fail and raise a FileNotFoundError")

    p = last_dir("a/b/c")
    assert p == "c"
    p = last_dir("d")
    assert p == "d"
    p = last_dir("/")
    assert p == ""

    p = parent_dir("a/b/c/")
    assert p == "a/b/c"
    p = parent_dir("a/b/c")
    assert p == "a/b"
    p = parent_dir("d")
    assert p == ""
    p = parent_dir("/")
    assert p == "/"

    p = root_path("a", "b", "c")
    assert p == "/a/b/c"
    p = root_path()
    assert p == "/"
    p = root_path("a", "b", "/", "c")
    assert p == "/c"

    # FIXME: how to test?
    current_dir()

    # FIXME: how to test?
    script_abspath("test.txt", "a")

    m = module_from_package("a.b.c")
    assert m == "c"
    m = module_from_package("a")
    assert m == "a"
    m = module_from_package("")
    assert m == ""

    p = project_dir("test")
    assert p == "./projects/test"
Beispiel #2
0
    def check_configuration(self, config_file_name):

        self.services_configuration = load_yaml_file(
            file=config_file_name,
            path=os.path.join(helpers.script_abspath(__file__), '..', '..',
                              CORE_CONFIG_PATH),
            logger=True)

        for service in self.services_configuration:

            name, prefix = self.prefix_name(service)

            # Was this service enabled from the developer?
            enable_var = str(prefix + 'enable').upper()
            self.available_services[name] = self.get_bool_from_os(enable_var)

            if self.available_services[name]:

                # read variables
                variables = self.load_variables(service, enable_var, prefix)
                service['variables'] = variables

                # set auth service
                if name == self.authentication_name:
                    self.authentication_service = variables.get('service')

        # log.pp(self.services_configuration)

        if self.authentication_service is None:
            raise AttributeError("no service defined behind authentication")
        else:
            log.info("Authentication based on '%s' service" %
                     self.authentication_service)
Beispiel #3
0
    def get_models(self):
        """ Read models from base/custom yaml files """

        filename = SWAGGER_MODELS_FILE

        # BASE definitions
        path = helpers.script_abspath(__file__, SWAGGER_DIR)
        data = load_yaml_file(filename, path=path)

        # CUSTOM definitions
        path = helpers.current_dir(CUSTOM_PACKAGE, SWAGGER_DIR)
        override = load_yaml_file(filename, path=path, skip_error=True)

        return mix(data, override)
Beispiel #4
0
    def find_endpoints(self):

        ##################
        # Walk swagger directories looking for endpoints

        # FIXME: how to do this?
        # from utilities import helpers
        # custom_dir = helpers.current_dir(CUSTOM_PACKAGE)
        # base_dir = helpers.script_abspath(__file__)

        base_swagger_confdir = helpers.script_abspath(__file__)
        custom_swagger_confdir = helpers.current_dir(CUSTOM_PACKAGE)

        # for base_dir in [BACKEND_PACKAGE, CUSTOM_PACKAGE]:
        for base_dir in [base_swagger_confdir, custom_swagger_confdir]:

            swagger_dir = os.path.join(base_dir, 'swagger')
            log.verbose("Swagger dir: %s" % swagger_dir)

            for ep in os.listdir(swagger_dir):

                swagger_endpoint_dir = os.path.join(swagger_dir, ep)

                if os.path.isfile(swagger_endpoint_dir):
                    exception = '%s.yaml' % SWAGGER_MODELS_FILE
                    if not swagger_endpoint_dir.endswith('/' + exception):
                        log.debug(
                            "Found a file instead of a folder: %s",
                            swagger_endpoint_dir
                        )
                    continue

                # isbase = base_dir == BACKEND_PACKAGE
                isbase = base_dir.startswith('/usr/local')
                base_module = helpers.last_dir(base_dir)
                from utilities import ENDPOINTS_CODE_DIR
                if isbase:
                    apiclass_module = '%s.%s' % (base_module, 'resources')
                else:
                    apiclass_module = '%s.%s' % (
                        base_module, ENDPOINTS_CODE_DIR)

                current = self.lookup(
                    ep, apiclass_module, swagger_endpoint_dir, isbase)
                if current is not None and current.exists:
                    # Add endpoint to REST mapping
                    self._endpoints.append(current)
Beispiel #5
0
    def get_models(self):
        """ Read models from base/custom yaml files """

        filename = SWAGGER_MODELS_FILE

        # BASE definitions
        path = helpers.script_abspath(__file__, SWAGGER_DIR)
        data = load_yaml_file(filename, path=path)

        # CUSTOM definitions
        path = helpers.current_dir(CUSTOM_PACKAGE, SWAGGER_DIR)
        override = load_yaml_file(filename,
                                  path=path,
                                  skip_error=True,
                                  logger=False)
        # NOTE: with logger=False I skip the warning if this file doesn't exist

        return mix(data, override)
Beispiel #6
0
#######################
# DEBUG level is 10 (https://docs.python.org/3/howto/logging.html)
CRITICAL_EXIT = 60
PRINT_STACK = 59
PRINT = 9
VERBOSE = 5
VERY_VERBOSE = 1
DEFAULT_LOGLEVEL_NAME = 'info'

MAX_CHAR_LEN = 200
OBSCURE_VALUE = '****'
OBSCURED_FIELDS = ['password', 'pwd', 'token', 'file', 'filename']

AVOID_COLORS_ENV_LABEL = "IDONTWANTCOLORS"
LOG_INI_FILE = os.path.join(helpers.script_abspath(__file__), 'logging.ini')
LOG_INI_TESTS_FILE = os.path.join(helpers.script_abspath(__file__),
                                  'logging_tests.ini')


#######################
@contextmanager
def suppress_stdout():
    """
    http://thesmithfam.org/blog/2012/10/25/
    temporarily-suppress-console-output-in-python/
    """
    with open(os.devnull, "w") as devnull:
        old_stdout = sys.stdout
        sys.stdout = devnull
        try:
Beispiel #7
0
def create_app(name=__name__,
               init_mode=False,
               destroy_mode=False,
               worker_mode=False,
               testing_mode=False,
               skip_endpoint_mapping=False,
               **kwargs):
    """ Create the server istance for Flask application """

    if PRODUCTION and testing_mode:
        log.exit("Unable to execute tests in production")

    #############################
    # Initialize reading of all files
    mem.customizer = Customizer(testing_mode, PRODUCTION, init_mode)
    # FIXME: try to remove mem. from everywhere...

    #############################
    # Add template dir for output in HTML
    from utilities import helpers
    tp = helpers.script_abspath(__file__, 'templates')
    kwargs['template_folder'] = tp

    #################################################
    # Flask app instance
    #################################################

    microservice = Flask(name, **kwargs)

    ##############################
    # Add commands to 'flask' binary
    if init_mode:
        microservice.config['INIT_MODE'] = init_mode
        skip_endpoint_mapping = True
    elif destroy_mode:
        microservice.config['DESTROY_MODE'] = destroy_mode
        skip_endpoint_mapping = True
    elif testing_mode:
        microservice.config['TESTING'] = testing_mode
        init_mode = True
        # microservice.config['INIT_MODE'] = init_mode
    elif worker_mode:
        skip_endpoint_mapping = True

    ##############################
    # Fix proxy wsgi for production calls
    microservice.wsgi_app = ProxyFix(microservice.wsgi_app)

    ##############################
    # Cors
    from restapi.protocols.cors import cors
    cors.init_app(microservice)
    log.verbose("FLASKING! Injected CORS")

    ##############################
    # Enabling our internal Flask customized response
    microservice.response_class = InternalResponse

    ##############################
    # Flask configuration from config file
    microservice.config.from_object(config)
    log.debug("Flask app configured")
    # log.pp(microservice.__dict__)

    ##############################
    if PRODUCTION:

        log.info("Production server mode is ON")

        # FIXME: random secrety key in production
        # # Check and use a random file a secret key.
        # install_secret_key(microservice)

        # # To enable exceptions printing inside uWSGI
        # # http://stackoverflow.com/a/17839750/2114395
        # from werkzeug.debug import DebuggedApplication
        # app.wsgi_app = DebuggedApplication(app.wsgi_app, True)

    ##############################
    # Find services and try to connect to the ones available
    extensions = detector.init_services(app=microservice,
                                        worker_mode=worker_mode,
                                        project_init=init_mode,
                                        project_clean=destroy_mode)

    if worker_mode:
        microservice.extensions = extensions

    ##############################
    # Restful plugin
    if not skip_endpoint_mapping:
        # Triggering automatic mapping of REST endpoints
        current_endpoints = create_endpoints(farmer.EndpointsFarmer(Api))
        # Restful init of the app
        current_endpoints.rest_api.init_app(microservice)

        ##############################
        # Injection!
        # Enabling "configuration modules" for services to be injected
        # IMPORTANT: Injector must be initialized AFTER mapping endpoints

        modules = detector.load_injector_modules()

        # AVOID warnings from Flask Injector
        warnings.filterwarnings("ignore")

        FlaskInjector(app=microservice, modules=modules)

        # otherwise...
        # Catch warnings from Flask Injector
        # try:
        #     FlaskInjector(app=microservice, modules=modules)
        # except RuntimeWarning:
        #     pass

    ##############################
    # Clean app routes
    ignore_verbs = {"HEAD", "OPTIONS"}

    for rule in microservice.url_map.iter_rules():

        rulename = str(rule)
        # Skip rules that are only exposing schemas
        if '/schemas/' in rulename:
            continue

        endpoint = microservice.view_functions[rule.endpoint]
        if not hasattr(endpoint, 'view_class'):
            continue
        newmethods = ignore_verbs.copy()

        for verb in rule.methods - ignore_verbs:
            method = verb.lower()
            if method in mem.customizer._original_paths[rulename]:
                # remove from flask mapping
                # to allow 405 response
                newmethods.add(verb)
            else:
                log.verbose("Removed method %s.%s from mapping" %
                            (rulename, verb))

        rule.methods = newmethods

        # FIXME: SOLVE CELERY INJECTION
        # # Set global objects for celery workers
        # if worker_mode:
        #     mem.services = internal_services

    ##############################
    # Logging responses
    @microservice.after_request
    def log_response(response):

        ###############################
        # NOTE: if it is an upload,
        # I must NOT consume request.data or request.json,
        # otherwise the content gets lost
        do_not_log_types = [
            'application/octet-stream',
            'multipart/form-data',
        ]

        if request.mimetype in do_not_log_types:
            data = 'STREAM_UPLOAD'
        else:
            try:
                data = handle_log_output(request.data)
                # Limit the parameters string size, sometimes it's too big
                for k in data:
                    try:
                        if not isinstance(data[k], str):
                            continue
                        if len(data[k]) > MAX_CHAR_LEN:
                            data[k] = data[k][:MAX_CHAR_LEN] + "..."
                    except IndexError:
                        pass
            except Exception as e:
                data = 'OTHER_UPLOAD'

        log.info("%s %s %s %s", request.method, request.url, data, response)

        return response

    ##############################
    # and the flask App is ready now:
    log.info("Boot completed")
    # return our flask app
    return microservice