Skip to content

Commit 7fc2f9e

Browse files
committed
initial commit
0 parents  commit 7fc2f9e

24 files changed

Lines changed: 728 additions & 0 deletions

β€ŽREADME.mdβ€Ž

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# python-web-tornado-api-posgres-raw-sql-simple
2+
3+
## Description
4+
Simple web app that serves an api
5+
for a tornado project.
6+
7+
Uses sqlalchemy and raw sql to query a table `dog`.
8+
9+
Remotely tested with *testify*.
10+
11+
## Tech stack
12+
- python
13+
- tornado
14+
- sqlalchemy
15+
- testify
16+
- requests
17+
18+
## Docker stack
19+
- python:latest
20+
- postgres:alpine
21+
22+
## To run
23+
`sudo ./install.sh -u`
24+
- Get all dogs: http://localhost/dog
25+
- Schema id, breed, and color
26+
- CRUD opperations
27+
- Create: curl -i -X PUT localhost/dog/<id>
28+
- Read: http://localhost/dog/<id>
29+
- Update: curl -i -X POST localhost/dog/<id>/<breed>/<color>
30+
- Delete: curl -i -X DELETE localhost/dog/<id>
31+
32+
## To stop
33+
`sudo ./install.sh -d`
34+
35+
## For help
36+
`sudo ./install.sh -h`
37+
38+
## Credit
39+
- [HTTPServer config](https://phrase.com/blog/posts/tornado-web-framework-i18n/)
40+
- [Code based on](https://www.tornadoweb.org/en/stable/)
41+
- [Sqlalchemy code](https://medium.com/swlh/tornado-and-sqlalchemy-847eecbc0445)

β€Ždb/sql/00-create-table.sqlβ€Ž

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CREATE SEQUENCE dog_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 2147483647 START 1;
2+
3+
CREATE TABLE "public"."dog" (
4+
"id" integer DEFAULT nextval('dog_id_seq') NOT NULL,
5+
"breed" text NOT NULL,
6+
"color" text NOT NULL
7+
) WITH (oids = false);

β€Ždb/sql/01-table-insert.sqlβ€Ž

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
INSERT INTO "animal"."public"."dog" (breed, color)
2+
VALUES
3+
('Am Bulldog', 'White'),
4+
('Blue Tick', 'Grey'),
5+
('Labrador', 'Black'),
6+
('Gr Shepard', 'Brown');

β€Ždocker-compose.ymlβ€Ž

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
version: "3.4"
2+
3+
services:
4+
db:
5+
image: postgres:alpine
6+
environment:
7+
- POSTGRES_DB=animal
8+
- POSTGRES_USER=maria
9+
- POSTGRES_HOST_AUTH_METHOD=trust
10+
volumes:
11+
- ./db/sql:/docker-entrypoint-initdb.d
12+
healthcheck:
13+
test: "exit 0"
14+
15+
py-srv:
16+
build:
17+
context: py-srv
18+
ports:
19+
- 80:8000
20+
healthcheck:
21+
test: "exit 0"
22+
command: sh -c "/wait && python app.py"
23+
environment:
24+
- WAIT_HOSTS=db:5432
25+
- WAIT_HOSTS_TIMEOUT=300
26+
- WAIT_SLEEP_INTERVAL=120
27+
- WAIT_HOST_CONNECT_TIMEOUT=30
28+
depends_on:
29+
- db
30+
links:
31+
- "db:db"
32+
33+
py-test-srv:
34+
build:
35+
context: py-test-srv
36+
command: sh -c "/wait && python app.py"
37+
environment:
38+
- WAIT_HOSTS=db:5432,py-srv:8000
39+
- WAIT_HOSTS_TIMEOUT=300
40+
- WAIT_SLEEP_INTERVAL=120
41+
- WAIT_HOST_CONNECT_TIMEOUT=30
42+
depends_on:
43+
- py-srv
44+
links:
45+
- "py-srv:py-srv"

β€Žgeneral.logβ€Ž

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[2023-04-20 10:09:48 INFO]: install::setup-logging ended
2+
================
3+
[2023-04-20 10:09:48 INFO]: install::start-up started
4+
[2023-04-20 10:09:48 INFO]: install::start-up starting services
5+
[2023-04-20 10:10:46 INFO]: install::root-check started
6+
[2023-04-20 10:10:46 INFO]: install::root-check ended
7+
================
8+
[2023-04-20 10:10:46 INFO]: install::docker-check started
9+
[2023-04-20 10:10:46 INFO]: install::docker-check ended
10+
================
11+
[2023-04-20 10:10:46 INFO]: install::docker-compose-check started
12+
[2023-04-20 10:10:46 INFO]: install::docker-compose-check ended
13+
================
14+
[2023-04-20 10:10:46 INFO]: install::tear-down started
15+
[2023-04-20 10:10:46 INFO]: install::tear-down starting services
16+
[2023-04-20 10:10:46 INFO]: install::tear-down ended
17+
================

β€Žinstall.shβ€Ž

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#!/usr/bin/env bash
2+
basefile="install"
3+
logfile="general.log"
4+
timestamp=`date '+%Y-%m-%d %H:%M:%S'`
5+
6+
if [ "$#" -ne 1 ]; then
7+
msg="[ERROR]: $basefile failed to receive enough args"
8+
echo "$msg"
9+
echo "$msg" >> $logfile
10+
exit 1
11+
fi
12+
13+
function setup-logging(){
14+
scope="setup-logging"
15+
info_base="[$timestamp INFO]: $basefile::$scope"
16+
17+
echo "$info_base started" >> $logfile
18+
19+
echo "$info_base removing old logs" >> $logfile
20+
21+
rm -f $logfile
22+
23+
echo "$info_base ended" >> $logfile
24+
25+
echo "================" >> $logfile
26+
}
27+
28+
function root-check(){
29+
scope="root-check"
30+
info_base="[$timestamp INFO]: $basefile::$scope"
31+
32+
echo "$info_base started" >> $logfile
33+
34+
#Make sure the script is running as root.
35+
if [ "$UID" -ne "0" ]; then
36+
echo "[$timestamp ERROR]: $basefile::$scope you must be root to run $0" >> $logfile
37+
echo "==================" >> $logfile
38+
echo "You must be root to run $0. Try the following"
39+
echo "sudo $0"
40+
exit 1
41+
fi
42+
43+
echo "$info_base ended" >> $logfile
44+
echo "================" >> $logfile
45+
}
46+
47+
function docker-check() {
48+
scope="docker-check"
49+
info_base="[$timestamp INFO]: $basefile::$scope"
50+
cmd=`docker -v`
51+
52+
echo "$info_base started" >> $logfile
53+
54+
if [ -z "$cmd" ]; then
55+
echo "$info_base docker not installed"
56+
echo "$info_base docker not installed" >> $logfile
57+
fi
58+
59+
echo "$info_base ended" >> $logfile
60+
echo "================" >> $logfile
61+
62+
}
63+
64+
function docker-compose-check() {
65+
scope="docker-compose-check"
66+
info_base="[$timestamp INFO]: $basefile::$scope"
67+
cmd=`docker-compose -v`
68+
69+
echo "$info_base started" >> $logfile
70+
71+
if [ -z "$cmd" ]; then
72+
echo "$info_base docker-compose not installed"
73+
echo "$info_base docker-compose not installed" >> $logfile
74+
fi
75+
76+
echo "$info_base ended" >> $logfile
77+
echo "================" >> $logfile
78+
79+
}
80+
function usage() {
81+
echo ""
82+
echo "Usage: "
83+
echo ""
84+
echo "-u: start."
85+
echo "-d: tear down."
86+
echo "-h: Display this help and exit."
87+
echo ""
88+
}
89+
function start-up(){
90+
91+
local scope="start-up"
92+
local docker_img_name=`head -n 1 README.md | sed 's/# //'`
93+
local info_base="[$timestamp INFO]: $basefile::$scope"
94+
95+
echo "$info_base started" >> $logfile
96+
97+
echo "$info_base starting services" >> $logfile
98+
99+
sudo docker-compose up --build
100+
101+
echo "$info_base ended" >> $logfile
102+
103+
echo "================" >> $logfile
104+
}
105+
function tear-down(){
106+
107+
scope="tear-down"
108+
info_base="[$timestamp INFO]: $basefile::$scope"
109+
110+
echo "$info_base started" >> $logfile
111+
112+
echo "$info_base starting services" >> $logfile
113+
114+
sudo docker-compose down
115+
116+
echo "$info_base ended" >> $logfile
117+
118+
echo "================" >> $logfile
119+
}
120+
121+
root-check
122+
docker-check
123+
docker-compose-check
124+
125+
while getopts ":udh" opts; do
126+
case $opts in
127+
u)
128+
setup-logging
129+
start-up ;;
130+
d)
131+
tear-down ;;
132+
h)
133+
usage
134+
exit 0 ;;
135+
/?)
136+
usage
137+
exit 1 ;;
138+
esac
139+
done

β€Žpy-srv/Dockerfileβ€Ž

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FROM python
2+
3+
RUN /usr/local/bin/python -m pip install --upgrade pip
4+
5+
COPY bin/ /app
6+
7+
WORKDIR /app
8+
9+
RUN pip install -r requirements.txt
10+
11+
CMD ["python", "app.py"]

β€Žpy-srv/bin/__init__.pyβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# __init__.py

β€Žpy-srv/bin/app.pyβ€Ž

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from tornado.httpserver import HTTPServer
2+
from tornado.ioloop import IOLoop
3+
from tornado.options import define, options
4+
from tornado.web import Application
5+
6+
from db.setup import sql_instance
7+
from handlers import *
8+
9+
define('host', default='0.0.0.0', help='Docker specific address')
10+
define('port', default=8000, help='port to listen on')
11+
12+
def main():
13+
"""Construct and serve the tornado application."""
14+
app = Application([
15+
('/', SmokeTestHandler)
16+
, ('/dog', GetHandler)
17+
, (r"/dog/([^/]+)", GetByFilterHandler)
18+
, (r"/dog/[0-9]", GetHandler)
19+
, (r"/dog/([^/]+)/([^/]+)", InsertHandler)
20+
, (r"/dog/([^/]+)/([^/]+)/([^/]+)", UpdateHandler)
21+
], db=sql_instance)
22+
23+
http_server = HTTPServer(app)
24+
http_server.listen(options.port, options.host)
25+
print(f'Listening on http://{options.host}:{options.port}')
26+
27+
IOLoop.current().start()
28+
29+
if __name__ == '__main__':
30+
main()

β€Žpy-srv/bin/db/__init__.pyβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# __init__.py

0 commit comments

Comments
 (0)