Esempio n. 1
0
    def _validate_initialization_type(self, settings_object: Config):
        if settings_object.INIESTA_INITIALIZATION_TYPE is None:
            raise ImproperlyConfigured(
                "Please configure INIESTA_INITIALIZATION_TYPE in your config!")

        if not isinstance(settings_object.INIESTA_INITIALIZATION_TYPE,
                          (list, tuple)):
            raise ImproperlyConfigured(
                "INIESTA_INITIALIZATION_TYPE type is invalid. Must be list or tuple!"
            )
Esempio n. 2
0
    def get_rate(self) -> str:
        """
        Determine the string representation of the allowed request rate.
        """
        if not getattr(self, "scope", None):
            msg = (
                "You must set either `.scope` or `.rate` for '%s' throttle" %
                self.__class__.__name__)
            raise ImproperlyConfigured(msg)

        try:
            return self.THROTTLE_RATES[self.scope]
        except KeyError:
            msg = "No default throttle rate set for '%s' scope" % self.scope
            raise ImproperlyConfigured(msg)
Esempio n. 3
0
    async def confirm_permission(self) -> None:
        """
        Confirms correct permissions are in place.

        :raises ImproperlyConfigured: If the permissions were not found.
        :raises AssertionError: If the permissions are not correctly configured on AWS.
        """
        session = BotoSession.get_session()
        async with session.create_client(
            "sqs",
            region_name=self.region_name or BotoSession.aws_default_region,
            endpoint_url=self.endpoint_url,
            aws_access_key_id=BotoSession.aws_access_key_id,
            aws_secret_access_key=BotoSession.aws_secret_access_key,
        ) as client:
            policy_attributes = await client.get_queue_attributes(
                QueueUrl=self.queue_url, AttributeNames=["Policy"]
            )

        try:
            policies = json.loads(policy_attributes["Attributes"]["Policy"])
            statement = policies["Statement"][0]
        except KeyError:
            raise ImproperlyConfigured("Permissions not found.")

        # need "Effect": "Allow", "Action": "SQS:SendMessage"
        assert statement["Effect"] == "Allow"
        assert "SQS:SendMessage" in statement["Action"]
Esempio n. 4
0
    def _init_event_polling(self, app: Insanic) -> None:
        """
        Initializes for event polling.

        Actions:

            - Checks if global arn exists
            - Checks if filters are 0 to avoid receiving all messages
            - Loads iniesta configs
            - Attaches listeners
            - Checks if queue exists (initialize)
            - Checks subscriptions
            - Checks permissions

        """

        self.load_config(app.config)
        if not app.config.INIESTA_DRY_RUN:
            # check if global arn exists
            self.check_global_arn(app.config)

            # check if filters are 0
            if len(app.config.INIESTA_SQS_CONSUMER_FILTERS) == 0:
                raise ImproperlyConfigured(
                    "INIESTA_SQS_CONSUMER_FILTERS is an empty list. "
                    "Please specify events to receive!")

            listener = IniestaListener()

            app.register_listener(listener.after_server_start_event_polling,
                                  "after_server_start")
            app.register_listener(listener.before_server_stop_stop_polling,
                                  "before_server_stop")
Esempio n. 5
0
    def configure_version(self, version: str) -> None:
        """
        Configures the application version and sets the
        version on settings. This is especially
        necessary for microservices.

        Precedence

        1. `version` argument

        2. APPLICATION_VERSION in settings

        3. defaults to `UNKNOWN`

        :param version: version of the service or application
        """

        if (settings.ENFORCE_APPLICATION_VERSION and version is None
                and settings.APPLICATION_VERSION is None):
            raise ImproperlyConfigured(
                "`version` must be included. Either set "
                "`ENFORCE_APPLICATION_VERSION` to False or include "
                "`version` when initializing Insanic. Or just include "
                "`APPLICATION_VERSION` in your config.`")
        settings.APPLICATION_VERSION = (version or settings.APPLICATION_VERSION
                                        or "UNKNOWN")
Esempio n. 6
0
 def _order_initialization_type(self, settings_object: Config) -> list:
     try:
         init_types = settings_object.INIESTA_INITIALIZATION_TYPE
         return sorted([InitializationTypes[it] for it in init_types])
     except (KeyError, TypeError):
         raise ImproperlyConfigured(
             f"{str(init_types)} is "
             f"an invalid initialization type. "
             f"Choices are {', '.join(str(i) for i in self.INITIALIZATION_MAPPING.keys())}"
         )
Esempio n. 7
0
    def verify_plugin_requirements(self) -> None:
        """
        Checks if the required plugins set in `REQUIRED_PLUGINS` have been
        installed and initialized.
        """

        for plugin in self.config.REQUIRED_PLUGINS:
            if plugin not in self.initialized_plugins.keys():
                raise ImproperlyConfigured(
                    f"{plugin} is defined in `REQUIRED_PLUGINS` in this "
                    f"environment but has not been initialized.")
Esempio n. 8
0
    def __getattr__(self, name):
        """Return the value of a setting and cache it in self.__dict__."""
        if self._wrapped is empty:
            self._setup(name)
        # val = self.__dict__.get(name) or getattr(self._wrapped, name)
        val = getattr(self._wrapped, name)

        # some special cases
        if name in {"SERVICE_NAME", "SECRET_KEY"} and not val:
            raise ImproperlyConfigured(
                "The SERVICE_NAME setting must not be empty.")

        self.__dict__[name] = val
        return val
Esempio n. 9
0
    def caches(self):
        if self._caches is None:
            caches = settings.INSANIC_CACHES

            for k, v in settings.CACHES.items():
                if k in caches:
                    raise ImproperlyConfigured(
                        f"Cannot override {k}.  This is a "
                        f"protected cache reserved for insanic use."
                    )
                caches.update({k: v})

            self._caches = caches

        return self._caches
Esempio n. 10
0
    def __call__(self, func_or_cls: [HTTPMethodView, Callable]):
        @wraps(func_or_cls)
        def wrapper(*args, **kwargs):

            request = None
            for arg in args:
                if isinstance(arg, Request):
                    request = arg
                    break

            view_response = func_or_cls(*args, **kwargs)

            if request:
                now = get_utc_timestamp()

                request_service = (
                    f"@{request.service.request_service.upper() or 'FE'}")
                request_type = f"{request.method} {request.uri_template}"
                key = (request_service, request.method, request.uri_template)

                if key not in self.last_call:
                    self.last_call[key] = now - self.ttl

                if self.last_call[key] + self.ttl <= now:
                    logger.warning(
                        f"[DEPRECATION WARNING] For maintainers of {request_service}! "
                        f"{request_type} will be deprecated on {self.dt}. "
                        f"You have {get_utc_datetime() - self.dt} left!")
                    self.last_call[key] = now

            return view_response

        if inspect.isclass(func_or_cls):
            if issubclass(func_or_cls, HTTPMethodView):
                for m in func_or_cls.http_method_names:
                    handler = getattr(func_or_cls, m.lower(), None)
                    if handler is None:
                        continue

                    setattr(func_or_cls, m.lower(), self.__call__(handler))

                return func_or_cls
            else:
                raise ImproperlyConfigured(
                    "Must wrap a HTTPMethodView subclass.")
        else:
            return wrapper
Esempio n. 11
0
    def _setup(self, name=None):
        """
        Load the settings module pointed to by the environment variable. This
        is used the first time we need any settings at all, if the user has not
        previously configured the settings manually.
        """

        settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
        if not settings_module:
            desc = ("setting %s" % name) if name else "settings"
            raise ImproperlyConfigured(
                "Requested %s, but settings are not configured. "
                "You must either define the environment variable %s "
                "or call settings.configure() before accessing settings." %
                (desc, ENVIRONMENT_VARIABLE))

        self._wrapped = self.config_class(settings_module)
Esempio n. 12
0
    def init_app(self, app: Insanic) -> None:
        """
        Initializes the application depending on INIESTA_INITIALIZATION_TYPE set in settings
        """
        if self._initialization_type is not empty:
            raise ImproperlyConfigured("Iniesta has already been initialized!")

        self.load_config(app.config)

        self._validate_initialization_type(app.config)

        initialization_types = self._order_initialization_type(app.config)

        for choice in initialization_types:
            initialization_method = self.INITIALIZATION_MAPPING[choice]
            initialization_method(app)
            self.initialization_type = choice
Esempio n. 13
0
 def check_global_arn(self, settings_object: Config) -> None:
     if settings_object.INIESTA_SNS_PRODUCER_GLOBAL_TOPIC_ARN is None:
         raise ImproperlyConfigured(
             "INIESTA_SNS_PRODUCER_GLOBAL_TOPIC_ARN not set in settings!")