The Fleet is an application designed for managing corporate fleets. Its purpose is to optimize the processes of repairs, insurance, inspections, and vehicle rentals.
DEV Stories | Microservices | How to use | Features | How to install & test
Read in different languages: PL EN
At first, my convention was to use a regular alembic to create a global migration for the entire project. This was a suboptimal solution that didn't naturally separate migrations for each of the microservices. That's why I decided to use flask-migrate in each microservice.
I conducted them following the guidelines from the documentation - https://flask.palletsprojects.com/en/3.0.x/testing/. For their execution, I used a separate test database. During their execution, I made an effort to clear table rows before each test iteration.
At the beginning of development I decided to store CORS policies for any URL with suffix '/*' in separate package inside of 'configuration.py' module. Although this implementation gives more separation between domains of configuration my call is to store it directly in app context, because it gives more compact code. Also storing policies in .env file looks like a 'overkill' to me.
Once coverage and sphinx docs are generated, they need to be deployed on separate as GitHub pages, and then removed from main repository to avoid messing up with 'Languages' highlights of repository. Here is example before and after:
At this particular project I decided to use pipenv over poetry as it seems to be more stable and up-to-date tool for virtual environments.
By reviewing code we can see that when it comes to loading environment variables I use python-dotenv package. Because every env file has '.env' filename, theoretically there is no need for using dotenv as pipenv loads those variables by default whenever their path is parallel with Pipfile. But dotenv will definitely will pay off then different naming conventions will see a daylight. Like 'test.env', 'serviceX.env', so I prefer to use this external package.
Creating routes for the "repairs" microservice, I began to wonder if I could introduce an implementation of connecting resources to the API that would be as orthogonal as possible to the application context in which configuration takes place. Orthogonality is the abstraction of a state in which changes in one element of the system do not affect its other elements. The approach I had developed so far was simple. Create a resource, import it into the configuration space, and finally add it to the existing API.
However, I often had to repeat this procedure for several resources. According to the principle of orthogonality, a change in one module should not necessitate changes outside of it. That's why I created the "RepairEndpointsMapper", where I define the resources I want to attach to the API on the fly.
The API itself is passed when the class is called. This way, the procedure transforms into: Assign the resource along with the path to the mapper, import the mapper, pass the API, and call the "init_endpoints" method. Now, if we want to add a resource, we simply add it to the mapper.
Automatic settings of a sample Chrome
web driver in selenium force us to install the Chromium engine in our environment and to use an output device, such as our monitor. However, in order to commercially create automation systems, we need to adapt to working in a Debian environment without extensions emulating a monitor.
Using the example of the cepik
microservice, which verifies whether our car has valid insurance and inspection, I will demonstrate how I configured selenium objects to work in a Docker container.
In the Dockerfile
of our microservice, we invoke commands to install the stable version of Google Chrome.
2. Adding arguments to the selenium.webdriver.chrome.options.Options
object to enable the proper functioning of the Selenium driver
In my code, I created a ChromeOptionsBuilder
, which provides all the necessary options that we need to add to the object.
--no-sandbox
allows avoiding issues with session creation.
--no-screen
disables the need for a screen.
--disable-dev-shm-usage
changes the cache location from shm to tmp, providing greater flexibility if multiple objects are working on shm.
The final creation of a driver that works correctly in a Docker container, considering the implementation of the options builder, looks as follows:
When creating unittests, attention should be paid to where to mock functions. For example, if I'm creating a module a.py
containing the function get_roberts_name
, mocking should focus on that function.
def get_roberts_name() -> str:
return 'Robert'
Now we create module b.py
, which will be importing get_roberts_name
from a import get_roberts_name
def top_customer() -> str:
return get_roberts_name()
Assuming we want to test top_customer
, but we don't want to depend on get_roberts_name
β diff at line 5
import pytest
from b import top_customer
def test_top_customer(mocker) -> None:
mocker.patch('b.get_roberts_name', side_effect=lambda *args, **kwargs: 'Adam')
assert top_customer() == 'Adam' # True
β diff at line 5
import pytest
from b import top_customer
def test_top_customer(mocker) -> None:
mocker.patch('a.get_roberts_name', side_effect=lambda *args, **kwargs: 'Adam')
assert top_customer() == 'Adam' # False
microservice | wiki | coverage |
---|---|---|
api-gateway | ||
cars | link | link |
mots | link | link |
insurances | link | link |
repairs | link | link |
aws-resources | ||
cepik | link | link |
external-resources-factory | ||
drivers | link | link |
notifications | ||
scheduler |
Deployed app π SOON
Functionality | State | Demo |
---|---|---|
CRUD Operations on Car | β | |
Authorization | β | |
Registration | β | |
Authentication via Email | β | |
CRUD Operations on Mot | β | |
CRUD Operations on Insurance | β | |
Storing static resources in Amazon S3 | β | |
Managing cars repairs | β | |
Validating MOT and Insurance using historia.pojazdu.gov | β | |
Generating full car history reports using historia.pojazdu.gov | β | |
Loading Cars, Mots, Insurances data from existing sources | β | |
CRUD Operations on Driver | β | |
Notifying Driver about expiring Mot and Insurance | β | |
Scheduling system notifications | β | |
UI | π οΈ |
β done π οΈ in progress π planned
βοΈ Docker βοΈ NodeJS βοΈ Python 3.11 βοΈ Current .env files - tutorial
git clone https://github.com/DSmolke/Flota.git
cd Flota
......
docker-compose up -d --build
docker ps
docker exec -it <CONTAINER-ID> bash
cd app
pipenv run flask --app "create_app:main" db upgrade head
cd ..
pipenv run pytest