The purpose of this project is to demonstrate the DevOps daily routine to manage the entire application development lifecycle, that is: Development, Testing, Deployment, and monitoring.
DevOpsDaily is a simple RESTful API application to provide access to a database of users and performing various actions on it.
For simplicity, the database will be stored as a simple JSON file in the following format:
users.json:
{
"duncan_long": {
"id": "drekaner",
"name": "Duncan Long",
"favorite_color": "Blue"
},
"kelsea_head": {
"id": "wagshark",
"name": "Kelsea Head",
"favorite_color": "Ping"
},
"phoenix_knox": {
"id": "jikininer",
"name": "Phoenix Knox",
"favorite_color": "Green"
},
"adina_norton": {
"id": "slimewagner",
"name": "Adina Norton",
"favorite_color": "Red"
}
}
The application exposes 3 endpoints:
• users.json File is stored in JsonPlaceHolder, which will be used as the db server, receiving HTTP get requests from the application.
• The application was built by using the simple Flask web Framework.
Once we have a working application, we should containerize it.
In order to do so, i'll be using Docker Desktop and build a container so users can run the following two commands:
$ docker build -t app:latest /path/to/Dockerfile
$ docker run -d -p 5000:5000 app
to assemble an image I used a Dockerfile
as follows:
FROM ubuntu:16.04
RUN apt-get update -y && \
apt-get install -y python-pip python-dev
# We copy just the requirements.txt first to leverage Docker cache
COPY ./requirements.txt /app/requirements.txt
WORKDIR /app
RUN pip install -r requirements.txt
COPY . /app
ENTRYPOINT [ "python" ]
CMD [ "app.py" ]
Using the docker build command builds an image from a Dockerfile and results as follows:
Using the docker run creates a container from the given image above and starts the container. results as follows:
Now we have the Application containerize and running as a proccess in the Docker.
In the tests stage we should write a simple unit-test for testing the functionality of the application. The unit-test creates a mock JSON database file (users.json) with predefined data, and validate that the application returns the correct information.
For example, given the following input file:
{
"test_user": {
"id": "test",
"name": "Test User",
"favorite_color": "Black"
}
}
(Test #1) Accessing the /users URI should return:
{
"test_user": {
"name": "Test User",
"favorite_color": "Black"
}
}
(Test #2) Accessing the /user/test_user URI should return:
{
"test_user": {
"id": "test",
"name": "Test User",
"favorite_color": "Black"
}
}
(Test #3) Accessing the /user/test_user123 URI should return HTTP code 404 as the user does not exist in the database.
• For this stage, I used Pytest framework to test the application functionality.
• For testing with mock JSON database file object, I have used the: unittest.mock library, which allows replacing parts of the system under test with mock objects and making assertions about how they have been used.
In the last stage, we have a working app that can also run inside a container, we should setup CI for it, so it won't break in the future. for setting up the CI I have used the following guidelines:
- Installed and Set up the project in Jenkins +configured required Jenkins Plugins to run Python Unit Test.
- Clone the application source code from a GitHub repository.
- Verify the result - run the unit-test and made sure all the tests pass.
- BONUS: Automatically execute the CI on every new pull request.
For Seting up the project in Jenkins I used "Build a free-style software project" and added a build step "Execute Windows batch command", with the following configuration:
echo '#### create Python3 Virtual Environment ####'
source scl_source enable rh-python36
VIRTUAL_ENV_NAME='virtual-environment'
py -m venv $VIRTUAL_ENV_NAME
echo '#### Avtivate Virtual Environment ####'
source $VIRTUAL_ENV_NAME/bin/activate
echo '#### Install requirments ####'
py -m pip install -r requirements.txt
py -m pip install --upgrade pip
echo '#### Run Tests ####'
py -m pytest --junitxml=test.xml
Configuring GitHub
running all unit-tests from test_application.py and getting Success.
running all unit-tests from test_application.py and getting failure by looking for a user which is exist in the fake database (mock JSON)(Test #3).
© 2020 Tal Mosenzon. All rights reserved.