Skip to main content

No project description provided

Project description

Metis-App

Introduction

Metis-App contains useful functions for the use primarily in Python-based AWS Lambda serverless functions. The majority of the functions are generic (rather than AWS-specifc), however, all these functions have been useful in building distributed serverless functions, based on local patterns.

The objective is to collect together useful functions found during the development of Lambda services.

For example, we have used monads (PyMonad) extensively for building composable pipelines and avoiding raising exceptions. In the monad lib there is also a try decorator than wraps exception-throwing functions. We have a simple circuit-breaker mechanism, and a method of performing an oauth client credentials grant.

This lib is not an AWS Lambda paved road or framework. Consider it as a collection of helpers.

The App Pipeline

The app pipeline is a common "middleware" manager for a Lambda event. The function initiates the pipeline right from the handle function. The pipeline takes care of building the request event structures, applying routing based on the event type (currently s3 nd http lambda events are supported), calls the function's handler, and generates the response. Other middleware services are also provided, such as creating a policy decision point (PDP) by parsing any token and calling an appropriate userinfo point.

The handler invokes the middleware as follows:

return app.pipeline(event=event,
                    context=context,
                    env=env.Env().env,
                    params_parser=request_builder,
                    pip_initiator=pip,
                    handler_guard_fn=check_env_established)
  • event. Mandatory. Dict. The Lambda provided event.
  • context. Mandatory. Dict. The Lambda provided context.
  • params_parser: Mandatory. Callable. Takes the request object optionally transforms it, and returns it wrapper in an Either. If no transformation is required simply return the request wrapped in an Either, e.g. return monad.Right(request)
  • pip_initiator: Mandatory. Callable. Policy Information Point
  • factory_overrides: Optional. Dict. Overrides the routing factory token constructor. Only supports S3 overrides. For an s3 override provide a Dict in the form of {'s3': callable_function}. With s3 the standard factory token constructor takes the bucket name, and splits on ".", returning the token prior to the first ".". As a convention it is expecting environment specific bucket names to be separated by ".", e.g. bucket-name.uat.example.io, with the resulting token being bucket-name. However, if this is not the format of the bucket name implement the override function. The function takes a List[S3Object] and must return a string to be looked up in the routing table. Note, should the event not be handled, return the const app.NO_MATCHING_ROUTE
  • handler_guard_fn: A pre-processing guard fn to determine whether the handler should be invoked. It returns an Either. When the handler shouldnt run the Either wraps an Exception. In this case, the request is passed directly to the responder

Using PowerTools Observability

Metis-app supports the integration of the AWS Powertools Logger, Tracer, and Metrics modules and decorators. To use them, install the dependencies and then build a Observer configuration in the handler module.

poetry add aws-lambda-powertools[aws-sdk]

# if using metrics...
poetry add aws-xray-sdk
from metis_app import observable

obs = observable.Observer().configure(service_name="test-service", metrics_namespace='module1')

Then use them as normal. Note, however, the logger, tracer, and metrics objects are now available through the observer object.

from aws_lambda_powertools.metrics import MetricUnit

@obs.metrics.log_metrics(capture_cold_start_metric=True)
def handler(event, ctx=None):
  ...
    

@obs.tracer.capture_method
def a_command(request):
    obs.tracer.put_annotation(key="Resource", value=request.event.path_params.get('id1'))
    obs.logger.info("Search for resource", uuid=request.event.path_params.get('id1'))
    obs.metrics.add_metric(name="Resource:Search", unit=MetricUnit.Count, value=1)
    ...

When the Observer is configured, it is also added to the Request object and passed to the command handler.

def a_command(request):
    request.observer.logger.info("Search for resource", uuid=request.event.path_params.get('id1'))
    ...

Getting a Self Token

Configuration

Provide the token service with a configuration as follows:

from metis_app import self_token

self_token.TokenConfig().configure(token_persistence_provider=TokenPersistenceProvider(),
                                   env=Env(),
                                   circuit_state_provider=circuit_store.CircuitStore(circuit_name="auth0"))
  • token_persistence_provider. A class that conforms to TokenPersistenceProviderProtocol. It has a write and read method.

    • The writer takes a key and value. The key defaults to BEARER_TOKEN, and the value is the JWT. It is the responsibility of the writer to persist where required. The writer must return the token wrapped in a Monad ; e.g. monad.Right('eyJ0eXAiOiJK....')
    • The reader takes a key and returns the value wrapped in a Monad; e.g. monad.Right('eyJ0eXAiOiJK....')
  • env. This should be a class that has the following methods:

    • client_id. Returns a client id as a string.
    • client_secret. Returns a client secret as a string.
    • identity_token_endpoint. Returns the url of the Oauth2 token endpoint as a str.
  • circuit_state_provider. Optional. A circuit state manager can optionally be provided. Doing so adds circuit breaker functionality to the call to the token endpoint. If not provided, failures do not enact the circuit breaker behaviour. The provider must conform to the circuit.CircuitStateProviderProtocol. This is a special case of a circuit; one that is used by the token getter. It will configure the circuit based on this arg. There is a more general way to use circuits for non-token interfaces. See the circuit breaker section.

Circuit Breaker

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

metis_app-0.4.19.tar.gz (33.0 kB view details)

Uploaded Source

Built Distribution

metis_app-0.4.19-py3-none-any.whl (39.4 kB view details)

Uploaded Python 3

File details

Details for the file metis_app-0.4.19.tar.gz.

File metadata

  • Download URL: metis_app-0.4.19.tar.gz
  • Upload date:
  • Size: 33.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.11.6 Darwin/23.5.0

File hashes

Hashes for metis_app-0.4.19.tar.gz
Algorithm Hash digest
SHA256 40c381bced3b757813f940da7f61ad861dd37bed9ec179edfca5bea04a65dfd2
MD5 261cc6d818bee9b1366375f0f37eaa46
BLAKE2b-256 2a25414a72346b41f680b250773842601b6cda3b56be9d2dfd7444b47d8e4468

See more details on using hashes here.

File details

Details for the file metis_app-0.4.19-py3-none-any.whl.

File metadata

  • Download URL: metis_app-0.4.19-py3-none-any.whl
  • Upload date:
  • Size: 39.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.11.6 Darwin/23.5.0

File hashes

Hashes for metis_app-0.4.19-py3-none-any.whl
Algorithm Hash digest
SHA256 5f9243ff1f3bba07962d2f25e07b6f52039bc0c28a5d0a521effe43f71b78ed0
MD5 e3507c18c4068afdf9797a00aed53354
BLAKE2b-256 84c64dab9ce013097c829b5e6deefb077180acb3ddd04640cd25fa9d2e478e88

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page