This is a basic Django backend app that does CRUD operations on Videos that are stored on disk.
In this project we use Ansible to deploy the app on a VM. So make sure you have ssh access(with sudo) to VM.
- Updating IP of server in hosts file.
- Changing
SERVER_DOMAIN
in constants.py to server IP or domain. Also if you are on http, you will have to changeplayback_url
that you get in response.
-
Make sure you have ansible setup from where you plan to run the deploy. You will need to generate GitHub token that you can use to clone private repo(https://github.com/settings/tokens/new) with
repo
access. -
Updated the server IP in hostgroup
django
in inventoryhosts
. -
Create a file called
vpass
which will be your vault password file with valueaaaa
which is your token value. OR run the command to do the same.echo "aaaa" > vpass
-
Run the playbook (make sure you are in parent folder of repo, no need to cd to any other dir)
ansible-playbook -b -K ansible/django_deploy.yml -i ansible/hosts --vault-password-file vpass -u <ssh-username> -e "github_user=<git-username>" -e "github_token=<token>"
The ansible flags may change as per how you want to ssh to servers, but should be more or less same.
This will setup everything from database, migrations and app.
Based on usecase, there are ansible tags defined that you can run.
To update the code, you need to run the ansible command with the tag deploy_app
.
For Nginx conf update run the tag nginx_deploy
.
Make a POST request with the local video file path to upload.
POST /videos
video_file
[REQUIRED]: absolute local file path of video that you want to upload.
video_name
[REQUIRED]: this will be the name of the video file on server.
video_folder
[REQUIRED]: name of the folder where the video will be stored. App automatically creates folder if it does not exists. The value can be empty string or should end with /
.
curl --location --request POST '<SRVER IP>/videos/' \
--form 'video_file=@"<VIDEO FILE PATH>"' \
--form 'video_name="<VIDEO NAME>"' \
--form 'video_folder="<DESTINATION VIDEO FOLDER>"'
Example:
curl --location --request POST '35.154.174.194/videos/' \
--form 'video_file=@"/Users/darshit/test.mp4"' \
--form 'video_name="github.mp4"' \
--form 'video_folder="ds/videos/"'
{
"id": 3,
"video_name": "github.mp4",
"size": "5253880",
"path": "ds/videos/",
"duration": "29.568000",
"codec": "mov,mp4,m4a,3gp,3g2,mj2",
"container": "isom",
"playback_url": "https://35.154.174.194/videos/play/ds/videos/github.mp4"
}
where,
size
is size of video in bytes.
duration
is video duration in seconds.
playback_url
is URL what you can use to play the video.
Make a GET request to list down all the videos in DB.
GET /videos
curl --location --request GET '<SERVER IP>/videos'
Example:
curl --location --request GET '35.154.174.194/videos'
Response to this GET request is list of videos with all metadata.
{
"videos": [
{
"id": 1,
"video_name": "testvid.mp4",
"size": 1,
"path": "dsdatsme/",
"duration": 1000.0,
"codec": "mov,mp4,m4a,3gp,3g2,mj2",
"container": "isom",
"playback_url": "https://35.154.174.194/videos/play/dsdatsme/testvid.mp4"
},
{
"id": 2,
"video_name": "test.mp4",
"size": 1,
"path": "dsdatsme2/",
"duration": 1000.0,
"codec": "mov,mp4,m4a,3gp,3g2,mj2",
"container": "isom",
"playback_url": "https://35.154.174.194/videos/play/dsdatsme2/test.mp4"
},
...
]
}
Make a GET request with video ID to get it's data.
GET /videos/<video id>
video id
[REQUIRED]: is an integer.
curl --location --request GET '<SERVER IP>/videos/<VIDEO ID>'
Example:
curl --location --request GET '35.154.174.194/videos/3'
Response will have all video metadata.
{
"id": 3,
"video_name": "github.mp4",
"size": "5253880",
"path": "ds/videos/",
"duration": "29.568000",
"codec": "mov,mp4,m4a,3gp,3g2,mj2",
"container": "isom",
"playback_url": "https://35.154.174.194/videos/play/ds/videos/github.mp4"
}
Make a PUT request with following options to update video metadata.
NOTE: currently only
path
andname
updates are supported.
PUT /videos/<video id>
video id
[REQUIRED]: is an integer.
video_name
[OPTIONAL]: send this if you want to rename a file.
video_folder
[OPTIONAL]: send this if you want to change the path of the file. The value can be empty string or should end with /
.
curl --location --request PUT '<SRVER IP>/videos/<VIDEO ID>' \
--form 'video_name="<NEW VIDEO NAME>"' \
--form 'video_folder="<NEW DESTINATION VIDEO FOLDER>"'
Example:
curl --location --request PUT '35.154.174.194/videos/3' \
--form 'video_name="new_github.mp4"' \
--form 'video_folder="ds/new_videos/"'
{
"id": 3,
"video_name": "new_github.mp4",
"size": "5253880",
"path": "ds/new_videos/",
"duration": "29.568000",
"codec": "mov,mp4,m4a,3gp,3g2,mj2",
"container": "isom",
"playback_url": "https://35.154.174.194/videos/play/ds/new_videos/new_github.mp4"
}
The response will have new metadata values along with updated URL.
Delete a particular video from server.
DELETE /videos/<video id>
video id
[REQUIRED]: is an integer.
curl --location --request DELETE '<SERVER IP>/videos/<VIDEO ID>'
Example:
curl --location --request DELETE '35.154.174.194/videos/3'
Response will have all video metadata of the deleted video.
{
"id": 3,
"video_name": "github.mp4",
"size": "5253880",
"path": "ds/videos/",
"duration": "29.568000",
"codec": "mov,mp4,m4a,3gp,3g2,mj2",
"container": "isom",
"playback_url": "https://35.154.174.194/videos/play/ds/videos/github.mp4"
}
SSH to the server and run the following command to restart the app
service video_app restart
To check the status
service video_app status
tail -f /tmp/video_app.log
cd /home/<user>/video_app/video_manager
docker-compose ls # check running
docker-compose restart # restart DB
less /etc/nginx/nginx.conf # main file
less /etc/nginx/conf.d/video_app.conf # app conf
service nginx status # check nginx process
service nginx restart # restart nginx process
nginx -t # test config
- Exception handling can be improved as various failure scenarios are not considered.
- Currently accepts all file format, but the upload will eventyally fail when app runs ffprobe.
- Video conflicts are checked later stage of the app, should be done before
- Use of serializers to sanity request and responses.
- Tests.
- Limit file size properly.
- Move app to docker container so that we dont need to manage virtual env.
- Once thats done, it can be easily deployed to k8s cluster and can be easily managed and scaled.
- Restrict Nginx to listen only single domain.
- If still plan to use Nginx, add redirect config for HTTP to HTTPS.
- If planning to move to k8s, use ingress and cert-manager. Example files can be found https://github.com/DSdatsme/golang-api-k8s-ci-cd.
- Use github actions to run test cases and build docker images. Example: https://github.com/DSdatsme/golang-api-k8s-ci-cd.