Tech Quickstart¶
This page gives a quick and partial introduction to CoWorks Technical Microservices. Follow Installation to install CoWorks and set up a new project.
CoWorks Technical Microservices are atomic microservices, meaning that they are single atomic components (i.e: singular blobs of code with a few inputs and outputs).
A tech microservice is simply defined by a single python class which looks like this:
class SimpleMicroService(TechMicroService):
def get(self):
return f"Simple microservice ready.\n"
Start¶
To create your first complete technical microservice, create a file hello.py
in the tech
folder
with the following content:
from coworks import TechMicroService
from coworks import entry
class HelloMicroService(TechMicroService):
@entry(no_auth=True)
def get(self):
return "Hello world.\n"
app = HelloMicroService()
This first example defines the very classical hello
microservice app
with a simple GET
entry /
(see Routing for more details on entry)
We set the attribute no_auth
to True
to allow access without authorization.
This effectively disables the token authorizer.
For security reason the default value is False
(see Authorization for more details on authorizer).
We now can launch the run
command defined by the Flask
framework. So to test this microservice locally
(see Flask for more details):
(project) $ cws --app hello run
* Stage: dev
* Serving Flask app 'hello'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
To test this example, open another terminal window and enter:
(project) $ curl http://127.0.0.1:5000/
Hello world.
If you remove the argument no_auth=True
from our @entry
decorator, you should instead receive a 403 response.
First¶
To add more elements, complete your first try with the following content:
from coworks import TechMicroService
from coworks import entry
class SimpleMicroService(TechMicroService):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.value = 0
def token_authorizer(self, token):
return token == "token"
@entry
def get(self):
return f"Stored value {self.value}.\n"
@entry
def post(self, value=None):
if value is not None:
self.value = value
return f"Value stored ({value}).\n"
app = SimpleMicroService(name="sample-first-microservice")
We have added a dedicated function token_authorizer
to define an authorizer
(see Authorization for more details on authorizer).
For this simple try, the authorizer validates the request only if a token is defined on header :
Authorization
key with token
as value.
Then we have defined two entries on same path : GET
and POST
on root path.
These enable reading and writing of our attribute value
.
To test this example, open another terminal window and enter:
(project) $ curl -I http://127.0.0.1:5000/
HTTP/1.0 401 UNAUTHORIZED
...
(project) $ curl -H "Authorization:token" http://127.0.0.1:5000/
Stored value 0.
(project) $ curl -X POST -d '{"value":20}' -H "Content-Type: application/json" -H "Authorization:token" http://127.0.0.1:5000/
Value stored (20).
(project) $ curl -H "Authorization:token" http://127.0.0.1:5000/
Stored value 20.
Beware : the value
is stored in memory just for this example, if the lambda is redeployed or another lambda instance
is used the value stored is lost.
Complete¶
We can create and test a more complete case by leveraging blueprints and adding middlewares. We will also use StringIO to write our output to a string buffer.
For more information on how CoWorks uses blueprints, see TechMS Blueprints. For more information on how CoWorks uses WSGI middlewares, see Middlewares.
First, ensure that aws_xray_sdk is installed in your python environment:
$ pip install aws-xray-sdk
Then, enter the following content:
from aws_xray_sdk.core import xray_recorder
from coworks import TechMicroService
from coworks import entry
from coworks.blueprint.admin_blueprint import Admin
from coworks.blueprint.profiler_blueprint import Profiler
from coworks.extension.xray import XRay
class SimpleMicroService(TechMicroService):
DOC_MD = """
#### Microservice Documentation
You can document your CoWorks MicroService using the class attributes `DOC_MD` (markdown) or
the instance attributes `doc_md` (markdown) which gets rendered from the '/' entry of the admin blueprint.
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.register_blueprint(Admin(), url_prefix='/admin')
self.register_blueprint(Profiler(self), url_prefix='/profile')
self.value = 0
@entry
def get(self):
return f"Stored value {self.value}.\n"
@entry
def post(self, value=None):
if value is not None:
self.value = value
return f"Value stored ({value}).\n"
app = SimpleMicroService(name="sample-complete-microservice")
XRay(app, xray_recorder)
Note : aws_xray_sdk must be installed in your python environment or you will get an ImportError
.
If you receive this error, follow the step above to install.
By default the token value should be defined in the TOKEN
environment variable ; the simpliest way to declare it
is to create a dotenv file (.env
) in the project folder with this token value defined in it:
TOKEN=mytoken
The Admin
blueprint adds several routes but
for the purposes of this example we’re interested in the root one (/admin
as prefixed):
This endpoint gives documentation and all the routes of the microservice with the signature extracted from its associated function.
We have also a WSGI middleware ProfilerMiddleware
to profile the last request:
(project) $ curl -H "Authorization:mytoken" http://127.0.0.1:5000/profile
--------------------------------------------------------------------------------
PATH: '/profile'
441 function calls (436 primitive calls) in 0.001 seconds
Ordered by: internal time, call count
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.000 0.000 {method 'getvalue' of '_io.StringIO' objects}
1 0.000 0.000 0.000 0.000 /home/gdo/.local/share/virtualenvs/samples-G9jKBMQA/lib/python3.10/site-packages/werkzeug/routing/map.py:246(bind_to_environ)
11 0.000 0.000 0.000 0.000 /home/gdo/.local/share/virtualenvs/samples-G9jKBMQA/lib/python3.10/site-packages/werkzeug/local.py:308(__get__)
...
And at last we have a CoWorks middleware to add XRay traces (available only for deployed microservices).
Deploy¶
And now we can upload the sources files to AWS S3 and apply predefined terraform planifications (options may be defined in project file to avoid given then on command line see Configuration ):
(project) $ cws deploy --bucket XXX --profile-name YYY --layers arn:aws:lambda:eu-west-1:935392763270:layer:coworks-ZZZ
Terraform apply (Create API routes)
Terraform apply (Deploy API and Lambda for the dev stage)
terraform output :
classical_id = "xxxxxxxx"
(project) $
Notice: To get the available coworks layer versions, just call this public microservice
(source code available in samples/layers
):
curl -H 'Accept:application/json' https://2kb9hn4bs4.execute-api.eu-west-1.amazonaws.com/v1
Now we can test our first deployed microservice:
(project) $ curl -H "Authorization:mytoken" https://xxxxxxxx.execute-api.eu-west-1.amazonaws.com/dev
Stored value 0.
Notice: The deploy parameters can be defined once in the project configuration file (project.cws.yml
)
Notice: You can set the debug option of Flask to get more information on the deploy process
(FLASK_DEBUG=1 cws deploy
)