Commit 2e705924 authored by Nane Kratzke's avatar Nane Kratzke
Browse files

Deploy

parent 3cfb4876
......@@ -15,6 +15,7 @@ Web-APIs sind Schnittstellen, um Informationen und Anwendungsfunktionen Nutzern
- [Vorbereitung](#vorbereitung)
- [Übung 01: Bauen Sie einen einfachen REST-Service](#übung-01-bauen-sie-einen-einfachen-rest-service)
- [Übung 02: Ergänzen Sie die Datenbank des Tutorials](#übung-02-ergänzen-sie-die-datenbank-des-tutorials)
- [Übung 03: Ergänzen Sie nun eine grafische Auswertung](#übung-03-ergänzen-sie-nun-eine-grafische-auswertung)
## Vorbereitung
......@@ -76,7 +77,41 @@ Committen und Pushen Sie nun diese Lösung in Git, um die Deployment Pipeline zu
- Geben Sie in Lens nun `kubectl port-forward svc/api-svc 8888:5000` ein.
- Öffnen Sie dann in einem Web-Browser die URL [http://localhost:8888](http://localhost:8888). Sie sollten dann erneut eine *"Distant Reading Archive"* Website sehen! Diesmal jedoch aus Kubernetes geliefert.
Setzen Sie nun das [Tutorial][tutorial] bis zum Punkt *API Design Principles* fort.
Setzen Sie nun das [Tutorial][tutorial] bis zum Punkt *API Design Principles* fort. Sie sollten nun den Book-API-Service in Kubernetes deployen. Wenn Sie mittels `kubectl port-forward svc/api-svc 5000:5000` die Book-API auf Ihren lokalen Rechner forwarden, sollten Sie folgende Links ohne Fehlermeldung abfragen können.
- [http://127.0.0.1:5000/api/v1/resources/books?id=1](http://127.0.0.1:5000/api/v1/resources/books?id=1) (Das Buch mit der Id 1)
- [http://127.0.0.1:5000/api/v1/resources/books/all](http://127.0.0.1:5000/api/v1/resources/books/all) (Alle Bücher)
> __Hinweis:__
> Wenn Sie gar nicht weiter wissen, können Sie mit `cp cheat/api-ue1.py api/api.py` ggf. etwas abkürzen.
## Übung 02: Ergänzen Sie die Datenbank des Tutorials
Setzen Sie nun das [Tutorial][tutorial] fort. Arbeiten Sie erst den Punkt *API Design Principles* durch. Machen Sie dann daran, die Datenbank zu integrieren.
Das Tutorial stellt eine sqlite-Datenbank mit diversen Buchpublikationen zur Verfügung. Diese ist in diesem Repository schon unter `api/books.db` hinterlegt und muss durch Sie nicht herunter geladen werden.
Sie sollten dann einen größeren Buchbestand flexibler abfragen können.
- [http://127.0.0.1:5000/api/v1/resources/books/all](http://127.0.0.1:5000/api/v1/resources/books/all)
- [http://127.0.0.1:5000/api/v1/resources/books?author=Connie+Willis](http://127.0.0.1:5000/api/v1/resources/books?author=Connie+Willis)
- [http://127.0.0.1:5000/api/v1/resources/books?author=Connie+Willis&published=1999](http://127.0.0.1:5000/api/v1/resources/books?author=Connie+Willis&published=1999)
- [http://127.0.0.1:5000/api/v1/resources/books?published=2010](http://127.0.0.1:5000/api/v1/resources/books?published=2010)
> __Hinweis:__
> Wenn Sie gar nicht weiter wissen, können Sie mit `cp cheat/api-ue2.py api/api.py` ggf. etwas abkürzen.
## Übung 03: Ergänzen Sie nun eine grafische Auswertung
Ergänzen Sie nun eine Route `/api/v1/resources/books/plot`. Diese soll nun die grafische Auswertung der Satzlängen über die Jahre des [Tutorials][tutorial] liefern. Das Datenformat soll SVG (Scalable Vector Grafic) sein.
Wenn Sie mittels `kubectl port-forward svc/api-svc 5000:5000` die Book-API auf Ihren lokalen Rechner forwarden, sollten Sie für folgende URL
- [http://127.0.0.1:5000/api/v1/resources/books/plot](http://127.0.0.1:5000/api/v1/resources/books/plot)
in etwa folgende Darstellung im Browser erhalten.
![TOP-10](top-10.svg)
> __Hinweis:__
> Wenn Sie gar nicht weiter wissen, können Sie mit `cp cheat/api-ue3.py api/api.py` ggf. etwas abkürzen.
\ No newline at end of file
FROM python:3.9-alpine
FROM python:3.9
COPY . /app/
RUN pip3 install flask
RUN pip3 install flask matplotlib
COPY . /app/
WORKDIR /app
EXPOSE 5000
ENTRYPOINT ["python3", "-u", "/app/api.py"]
ENTRYPOINT ["python3", "-u", "api-ue3.py"]
import flask
from flask import request, jsonify
import sqlite3
import matplotlib.pyplot as plt
import numpy as np
import string, re
app = flask.Flask(__name__)
app.config["DEBUG"] = True
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
@app.route('/', methods=['GET'])
def home():
return '''<h1>Distant Reading Archive</h1>
<p>A prototype API for distant reading of science fiction novels.</p>'''
@app.route('/api/v1/resources/books/all', methods=['GET'])
def api_all():
conn = sqlite3.connect('books.db')
conn.row_factory = dict_factory
cur = conn.cursor()
all_books = cur.execute('SELECT * FROM books;').fetchall()
return jsonify(all_books)
@app.route('/api/v1/resources/books/plot', methods=['GET'])
def book_plot():
conn = sqlite3.connect('books.db')
conn.row_factory = dict_factory
cur = conn.cursor()
all_books = cur.execute('SELECT * FROM books;').fetchall()
ys = np.array([len(book['first_sentence']) for book in all_books])
xs = np.array([book['published'] for book in all_books])
m, b = np.polyfit(xs, ys, 1)
fig = plt.figure()
plt.scatter(xs, ys, color="red")
plt.plot(xs, m * xs + b, color="blue")
plt.xlabel("Date of Publication")
plt.ylabel("Length of First Sentence in Characters")
plt.savefig("top-10.svg")
return flask.Response(open("top-10.svg").read(), mimetype='image/svg+xml')
@app.errorhandler(404)
def page_not_found(e):
return "<h1>404</h1><p>The resource could not be found.</p>", 404
@app.route('/api/v1/resources/books', methods=['GET'])
def api_filter():
query_parameters = request.args
id = query_parameters.get('id')
published = query_parameters.get('published')
author = query_parameters.get('author')
query = "SELECT * FROM books WHERE"
to_filter = []
if id:
query += ' id=? AND'
to_filter.append(id)
if published:
query += ' published=? AND'
to_filter.append(published)
if author:
query += ' author=? AND'
to_filter.append(author)
if not (id or published or author):
return page_not_found(404)
query = query[:-4] + ';'
conn = sqlite3.connect('books.db')
conn.row_factory = dict_factory
cur = conn.cursor()
results = cur.execute(query, to_filter).fetchall()
return jsonify(results)
app.run(host="0.0.0.0")
\ No newline at end of file
import flask
from flask import request, jsonify
app = flask.Flask(__name__)
# Create some test data for our catalog in the form of a list of dictionaries.
books = [
{'id': 0,
'title': 'A Fire Upon the Deep',
'author': 'Vernor Vinge',
'first_sentence': 'The coldsleep itself was dreamless.',
'year_published': '1992'},
{'id': 1,
'title': 'The Ones Who Walk Away From Omelas',
'author': 'Ursula K. Le Guin',
'first_sentence': 'With a clamor of bells that set the swallows soaring, the Festival of Summer came to the city Omelas, bright-towered by the sea.',
'published': '1973'},
{'id': 2,
'title': 'Dhalgren',
'author': 'Samuel R. Delany',
'first_sentence': 'to wound the autumnal city.',
'published': '1975'}
]
@app.route('/', methods=['GET'])
def home():
return '''<h1>Distant Reading Archive</h1>
<p>A prototype API for distant reading of science fiction novels.</p>'''
@app.route('/api/v1/resources/books/all', methods=['GET'])
def api_all():
return jsonify(books)
@app.route('/api/v1/resources/books', methods=['GET'])
def api_id():
# Check if an ID was provided as part of the URL.
# If ID is provided, assign it to a variable.
# If no ID is provided, display an error in the browser.
if 'id' in request.args:
id = int(request.args['id'])
else:
return "Error: No id field provided. Please specify an id."
# Create an empty list for our results
results = []
# Loop through the data and match results that fit the requested ID.
# IDs are unique, but other fields might return many results
for book in books:
if book['id'] == id:
results.append(book)
# Use the jsonify function from Flask to convert our list of
# Python dictionaries to the JSON format.
return jsonify(results)
app.run(host="0.0.0.0")
\ No newline at end of file
import flask
from flask import request, jsonify
import sqlite3
app = flask.Flask(__name__)
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
@app.route('/', methods=['GET'])
def home():
return '''<h1>Distant Reading Archive</h1>
<p>A prototype API for distant reading of science fiction novels.</p>'''
@app.route('/api/v1/resources/books/all', methods=['GET'])
def api_all():
conn = sqlite3.connect('books.db')
conn.row_factory = dict_factory
cur = conn.cursor()
all_books = cur.execute('SELECT * FROM books;').fetchall()
return jsonify(all_books)
@app.errorhandler(404)
def page_not_found(e):
return "<h1>404</h1><p>The resource could not be found.</p>", 404
@app.route('/api/v1/resources/books', methods=['GET'])
def api_filter():
query_parameters = request.args
id = query_parameters.get('id')
published = query_parameters.get('published')
author = query_parameters.get('author')
query = "SELECT * FROM books WHERE"
to_filter = []
if id:
query += ' id=? AND'
to_filter.append(id)
if published:
query += ' published=? AND'
to_filter.append(published)
if author:
query += ' author=? AND'
to_filter.append(author)
if not (id or published or author):
return page_not_found(404)
query = query[:-4] + ';'
conn = sqlite3.connect('books.db')
conn.row_factory = dict_factory
cur = conn.cursor()
results = cur.execute(query, to_filter).fetchall()
return jsonify(results)
app.run(host="0.0.0.0")
\ No newline at end of file
import flask
from flask import request, jsonify
import sqlite3
import matplotlib.pyplot as plt
import numpy as np
import string, re
app = flask.Flask(__name__)
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
@app.route('/', methods=['GET'])
def home():
return '''<h1>Distant Reading Archive</h1>
<p>A prototype API for distant reading of science fiction novels.</p>'''
@app.route('/api/v1/resources/books/all', methods=['GET'])
def api_all():
conn = sqlite3.connect('books.db')
conn.row_factory = dict_factory
cur = conn.cursor()
all_books = cur.execute('SELECT * FROM books;').fetchall()
return jsonify(all_books)
@app.route('/api/v1/resources/books/plot', methods=['GET'])
def book_plot():
conn = sqlite3.connect('books.db')
conn.row_factory = dict_factory
cur = conn.cursor()
all_books = cur.execute('SELECT * FROM books;').fetchall()
ys = np.array([len(book['first_sentence']) for book in all_books])
xs = np.array([book['published'] for book in all_books])
m, b = np.polyfit(xs, ys, 1)
fig = plt.figure()
plt.scatter(xs, ys, color="red")
plt.plot(xs, m * xs + b, color="blue")
plt.xlabel("Date of Publication")
plt.ylabel("Length of First Sentence in Characters")
plt.savefig("top-10.svg")
return flask.Response(open("top-10.svg").read(), mimetype='image/svg+xml')
@app.errorhandler(404)
def page_not_found(e):
return "<h1>404</h1><p>The resource could not be found.</p>", 404
@app.route('/api/v1/resources/books', methods=['GET'])
def api_filter():
query_parameters = request.args
id = query_parameters.get('id')
published = query_parameters.get('published')
author = query_parameters.get('author')
query = "SELECT * FROM books WHERE"
to_filter = []
if id:
query += ' id=? AND'
to_filter.append(id)
if published:
query += ' published=? AND'
to_filter.append(published)
if author:
query += ' author=? AND'
to_filter.append(author)
if not (id or published or author):
return page_not_found(404)
query = query[:-4] + ';'
conn = sqlite3.connect('books.db')
conn.row_factory = dict_factory
cur = conn.cursor()
results = cur.execute(query, to_filter).fetchall()
return jsonify(results)
app.run(host="0.0.0.0")
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment