Skip to content

Commit 43a1bb6

Browse files
committed
lab 14 - api frontend
1 parent c48166d commit 43a1bb6

File tree

7 files changed

+474
-0
lines changed

7 files changed

+474
-0
lines changed

dragon_w_3_micro.py

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
Dragon Cafe Microservices Application, with Menu, Login, and Fortune Cookie Microservice
5+
6+
Author: Sam Griffith | Org: Alta3 Research Inc.
7+
8+
This is a transitional application that has both the old routes and the new /v2 routes available.
9+
10+
The /v2 routes are essentially redirects to their respective microservices
11+
"""
12+
13+
from aiohttp import web
14+
import jinja2
15+
from pathlib import Path
16+
import random
17+
import requests
18+
import socket
19+
import os
20+
import json
21+
22+
HOST = os.getenv("DRAGON_HOST", "0.0.0.0")
23+
LOCAL_IP = socket.gethostbyname(socket.gethostname())
24+
PORT = os.getenv("DRAGON_PORT", 2225)
25+
REG_ADDR = os.getenv("SR_ADDRESS", "127.0.0.1")
26+
REG_PORT = os.getenv("SR_PORT", 55555)
27+
SERVICE = os.path.basename(__file__).rstrip(".py")
28+
29+
30+
class Page:
31+
def __init__(self, filename, templates_dir=Path("templates"), args={}, cookies={}):
32+
"""
33+
Create a new instance of an html page to be returned
34+
:param filename: name of file found in the templates_dir
35+
"""
36+
self.path = templates_dir
37+
self.file = templates_dir / filename
38+
self.args = args
39+
self.cookies = cookies
40+
41+
def render(self):
42+
with open(self.file) as f:
43+
txt = f.read()
44+
print(f"Templating in {self.args}")
45+
j2 = jinja2.Template(txt).render(self.args)
46+
resp = web.Response(text=j2, content_type='text/html')
47+
for c, j in self.cookies:
48+
resp.set_cookie(c, j)
49+
return resp
50+
51+
52+
def routes(app: web.Application) -> None:
53+
app.add_routes(
54+
[
55+
web.get("/", home),
56+
web.get("/login", login),
57+
web.get("/v2/login", login_v2),
58+
web.get("/v2/login/{ex_path}", login_v2),
59+
web.post("/logging_in", logging_in),
60+
web.get("/fortune_cookie", fortune_cookie),
61+
web.get("/v2/fortune_cookie", fortune_cookie_v2),
62+
web.get("/v2/fortune_cookie/{ex_path}", fortune_cookie_v2),
63+
web.get("/fortune", fortune),
64+
web.get("/menu", menu),
65+
web.get("/v2/menu", menu_v2)
66+
]
67+
)
68+
69+
async def login_v2(request) -> web.Response:
70+
print(request)
71+
ex_path = request.match_info.get('ex_path', '')
72+
login_svc = requests.get("http://127.0.0.1:55555/get_one/login").text
73+
print(login_svc)
74+
login_host = json.loads(login_svc)
75+
login_ip = login_host['endpoints'][0]
76+
login_port = login_host['endpoints'][1]
77+
if request.method == "POST":
78+
data = await request.post()
79+
r = requests.post(f"http://{login_ip}:{login_port}/login/{ex_path}", data=data)
80+
if ex_path == '':
81+
r = requests.get(f"http://{login_ip}:{login_port}/login")
82+
else:
83+
r = requests.get(f"http://{login_ip}:{login_port}/login/{ex_path}")
84+
return web.Response(text=r.text, content_type='text/html')
85+
86+
87+
async def fortune_cookie_v2(request) -> web.Response:
88+
print(request)
89+
ex_path = request.match_info.get('ex_path', '')
90+
fortune_cookie_svc = requests.get("http://127.0.0.1:55555/get_one/fortune_cookie").text
91+
print(fortune_cookie_svc)
92+
fortune_cookie_host = json.loads(fortune_cookie_svc)
93+
fortune_cookie_ip = fortune_cookie_host['endpoints'][0]
94+
fortune_cookie_port = fortune_cookie_host['endpoints'][1]
95+
if ex_path == '':
96+
r = requests.get(f"http://{fortune_cookie_ip}:{fortune_cookie_port}/fortune_cookie")
97+
else:
98+
r = requests.get(f"http://{fortune_cookie_ip}:{fortune_cookie_port}/fortune_cookie/{ex_path}")
99+
return web.Response(text=r.text, content_type='text/html')
100+
101+
102+
async def menu_v2(request):
103+
print(request)
104+
menu_svc = requests.get("http://127.0.0.1:55555/get_one/menu").text
105+
print(menu_svc)
106+
menu_host = json.loads(menu_svc)
107+
menu_ip = menu_host['endpoints'][0]
108+
menu_port = menu_host['endpoints'][1]
109+
r = requests.get(f"http://{menu_ip}:{menu_port}/menu")
110+
return web.Response(text=r.text, content_type='text/html')
111+
112+
113+
async def home(request) -> web.Response:
114+
"""
115+
This is the home page for the website
116+
"""
117+
print(request)
118+
page = Page(filename="index.html")
119+
return page.render()
120+
121+
122+
async def logging_in(request):
123+
"""
124+
This is the page that gets POSTED to allow a user to login
125+
"""
126+
print(request)
127+
if request.method == 'POST':
128+
data = await request.post()
129+
name = data['name']
130+
print("POSTED")
131+
print(name)
132+
# TODO - Add authentication logic
133+
get_login = await login(request, name=name)
134+
return get_login
135+
136+
137+
async def login(request, name=None):
138+
"""
139+
This is the login page for the website
140+
"""
141+
print(request)
142+
if name is not None:
143+
page = Page(filename="hello.html", args={"name": name})
144+
print("Cookies Set?")
145+
return page.render()
146+
else:
147+
print("No name has been sent yet!")
148+
args = {"name": name}
149+
page = Page(filename="login.html", args=args)
150+
return page.render()
151+
152+
153+
async def fortune_cookie(request) -> web.Response:
154+
"""
155+
This is the initial landing page for the fortune_cookie service.
156+
157+
Click on the link provided to retrieve your fortune!
158+
"""
159+
print(request)
160+
page = Page(filename="fortune_cookie.html")
161+
return page.render()
162+
163+
164+
async def fortune(request) -> web.Response:
165+
"""
166+
This returns a randomly picked aphorism as a part of the fortune_cookie service.
167+
"""
168+
print(request)
169+
170+
171+
possible = [
172+
"People are naturally attracted to you.",
173+
"You learn from your mistakes... You will learn a lot today.",
174+
"If you have something good in your life, don't let it go!",
175+
"What ever you're goal is in life, embrace it visualize it, and for it will be yours.",
176+
"Your shoes will make you happy today.",
177+
"You cannot love life until you live the life you love.",
178+
"Be on the lookout for coming events; They cast their shadows beforehand.",
179+
"Land is always on the mind of a flying bird.",
180+
"The man or woman you desire feels the same about you.",
181+
"Meeting adversity well is the source of your strength.",
182+
"A dream you have will come true.",
183+
"Our deeds determine us, as much as we determine our deeds.",
184+
"Never give up. You're not a failure if you don't give up.",
185+
"You will become great if you believe in yourself.",
186+
"There is no greater pleasure than seeing your loved ones prosper.",
187+
"You will marry your lover.",
188+
"A very attractive person has a message for you.",
189+
"You already know the answer to the questions lingering inside your head.",
190+
"It is now, and in this world, that we must live.",
191+
"You must try, or hate yourself for not trying.",
192+
"You can make your own happiness.",
193+
"The greatest risk is not taking one.",
194+
"The love of your life is stepping into your planet this summer.",
195+
"Love can last a lifetime, if you want it to.",
196+
"Adversity is the parent of virtue.",
197+
"Serious trouble will bypass you.",
198+
"A short stranger will soon enter your life with blessings to share.",
199+
"Now is the time to try something new.",
200+
"Wealth awaits you very soon.",
201+
"If you feel you are right, stand firmly by your convictions.",
202+
"If winter comes, can spring be far behind?",
203+
"Keep your eye out for someone special.",
204+
"You are very talented in many ways.",
205+
"A stranger, is a friend you have not spoken to yet.",
206+
"A new voyage will fill your life with untold memories.",
207+
"You will travel to many exotic places in your lifetime.",
208+
"Your ability for accomplishment will follow with success.",
209+
"Nothing astonishes men so much as common sense and plain dealing.",
210+
"Its amazing how much good you can do if you do not care who gets the credit.",
211+
"Everyone agrees. You are the best.",
212+
"Life consist not in holding good cards, but in playing those you hold well.",
213+
"Jealousy doesn't open doors, it closes them!",
214+
"It's better to be alone sometimes.",
215+
"When fear hurts you, conquer it and defeat it!",
216+
"Let the deeds speak.",
217+
"You will be called in to fulfill a position of high honor and responsibility.",
218+
"The man on the top of the mountain did not fall there.",
219+
"You will conquer obstacles to achieve success.",
220+
"Joys are often the shadows, cast by sorrows.",
221+
"Fortune favors the brave.",
222+
]
223+
fortune_choice = random.choice(possible)
224+
args = {"fortune": fortune_choice}
225+
page = Page(filename="fortune.html", args=args)
226+
return page.render()
227+
228+
229+
async def menu(request) -> web.Response:
230+
"""
231+
This will return the jinja2 templated menu.html file.
232+
"""
233+
print(request)
234+
food_items = [
235+
{"item": "General Tzo's Chicken", "description": "Yummy chicken on rice", "price": 12.99},
236+
{"item": "Kung Pao Beef", "description": "Spicy Beef on rice", "price": 13.99}
237+
] # TODO - Update to a sqlite3 database call
238+
args = {"foods": food_items}
239+
page = Page(filename="menu.html", args=args)
240+
return page.render()
241+
242+
243+
async def register(add_to_registry=True):
244+
print(f"""
245+
Service Registry {REG_ADDR}:{REG_PORT}
246+
247+
Adding to the Service Registry:
248+
249+
service name {SERVICE}
250+
service IP {LOCAL_IP}
251+
service port {PORT}
252+
""")
253+
if add_to_registry:
254+
r = requests.get(f"http://{REG_ADDR}:{REG_PORT}/add/{SERVICE}/{LOCAL_IP}/{PORT}")
255+
print(r.status_code, r.text)
256+
257+
258+
async def unregister(remove_from_registry=True):
259+
if remove_from_registry:
260+
r = requests.get(f"http://{REG_ADDR}:{REG_PORT}/remove/{SERVICE}/{LOCAL_IP}/{PORT}")
261+
print(r.status_code)
262+
263+
264+
def main():
265+
"""
266+
This is the main process for the aiohttp server.
267+
268+
This works by instantiating the app as a web.Application(),
269+
then applying the setup function we built in our routes
270+
function to add routes to our app, then by starting the async
271+
event loop with web.run_app().
272+
"""
273+
274+
print("This aiohttp web server is starting up!")
275+
app = web.Application()
276+
routes(app)
277+
app.on_startup.append(register)
278+
app.on_shutdown.append(unregister)
279+
web.run_app(app, host=HOST, port=PORT)
280+
281+
282+
if __name__ == "__main__":
283+
main()

microservices/api_gateway/Dockerfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FROM python:3.8-slim
2+
COPY requirements.txt /home/ubuntu/requirements.txt
3+
RUN pip3 install -r /home/ubuntu/requirements.txt
4+
COPY api_gateway.py /home/ubuntu/api_gateway.py
5+
COPY templates /home/ubuntu/templates
6+
WORKDIR /home/ubuntu/
7+
CMD ["python3", "/home/ubuntu/api_gateway.py"]
8+
EXPOSE 80

0 commit comments

Comments
 (0)