EOSC-Synergy
EGI SSO
- Do skorzystania z zasobów w ramach EOSC-Synergy każdy z Państwa musi mieć tożsamość (identity) w ramach EGI - federacji centrów obliczeniowych i dostawców pamięci masowej (więcej info o EGI tutaj)
- EGI AAI (Authentication and Authorization Infrastructure) wspiera obecnie wielu dostawców tożsamości (identity provider) np. Google, GitHub, Bitbucket
- Można też założyć konto w EGI SSO (Single Sign-On)
VO university.eosc-eynergy.eu
- Po uzyskaniu konta/tożsamości EGI należy jeszcze dołączyć do VO university.eosc-synergy.eu (Virtual Organization)
- Zgłoszony wniosek musi być zaakceptowany przez koordynatora, więc może to potrwać
Cel
- Laboratoria z przedmiotu Aplikacje w chmurze mają następujące cele:
- Nauczyć jak uruchamiać własne aplikacje w chmurze
- Przekazać dobre praktyki odnośnie tworzenia projektów z przeznaczeniem do działania w chmurze
- Zademonstrować przegląd przydatnych technologii DevOps
Zadanie
- Na potrzeby tego przedmiotu będziemy tworzyli projekt składający się z bazy danych, backendu i frontendu
- Projekt można realizować w zespołach 2-3 osobowych
- W kolejnych etapach będziemy przy pomocy różnych technologii przenosić projekt do chmury
Baza danych
- Zapoznaj się z projektem awesomedata/awesome-public-datasets
- Wybierz któryś zbiór danych np.:
- Dobrze gdyby w grupie wybrane były różnorodne bazy danych
- Wybrany zestaw danych ściągnij sobie lokalnie
- Przygotuj sobie lokalnie schemat bazy danych SQL (np. PostgreSQL) albo NoSQL (np. MongoDB)
- Przygotuj kod do zaimportowania danych do bazy
Backend
- Backend powinien wspierać:
- Ściągnięcie wszystkiego z bazy danych (ocena 3.0) np.
GET /objects
- Filtrowanie po jednym kryterium (ocena 3.5) np.
GET /object?name=xyz
- Dodawanie nowych rekordów (ocena 4.0) np.
PUT /object
- Modyfikację istniejących rekordów (ocena 4.5) np.
POST /object
- Zaawansowane przetwarzanie (ocena 5.0) np.
GET /stats
- Ostatni punkt dotyczy funkcji dopasowanej do domeny bazy danych np. zaproponowanie hasła niedostępnego w słownikach, policzenia statystyk, wygenerowanie raportu, itp.
Frontend
- Frontend nie musi być wyszukany wizualnie
- Jego zadaniem jest wspierać poszczególne funkcje z backendu (pokazanie wszystkich rekordów lub tylko wybranych, itd.)
Technologie
- Każdy podprojekt może być przygotowany w dowolnej technologii
- Przykładowe biblioteki / frameworki:
Przykład
Baza danych
plantlst.txt
"Symbol","Synonym Symbol","Scientific Name with Author","Common Name","Family"
"ABAB","","Abutilon abutiloides (Jacq.) Garcke ex Hochr.","shrubby Indian mallow","Malvaceae"
"ABAB","ABAM5","Abutilon americanum (L.) Sweet","",""
...
insert.py
#! /usr/bin/env python
import csv
import pymongo
if __name__ == '__main__':
columns = ["Symbol", "Synonym Symbol", "Scientific Name with Author", "Common Name", "Family"]
entries = []
with open('plantlst.txt') as infile:
reader = csv.reader(infile)
next(reader) # skip the first line
for row in reader:
entries.append(dict(zip(columns, row)))
client = pymongo.MongoClient('mongodb://localhost:27017')
db = client['db']
plants = db['plants']
plants.insert_many(entries)
Sprawdzenie czy działa jak należy
$ mongo
> use db
> db.plants.count()
90909
Backend
backend.py
#! /usr/bin/env python
import pymongo
from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class Plants(Resource):
def __init__(self):
self.client = pymongo.MongoClient('mongodb://localhost:27017')
self.db = self.client['db']
self.plants = self.db['plants']
self.columns = ["Symbol", "Synonym Symbol", "Scientific Name with Author", "Common Name", "Family"]
def get(self):
results = self.plants.find({}, {'_id': 0})
results = list(map(dict, results))
return results
api.add_resource(Plants, '/')
if __name__ == '__main__':
app.run(debug=True, port=5000)
Sprawdzenie czy działa jak należy
$ curl -s http://localhost:5000 | jq '. | length'
90909
Frontend
frontend.py
#! /usr/bin/env python
from flask import Flask, render_template
import requests
app = Flask(__name__, template_folder='templates')
@app.route('/')
def index():
r = requests.get('http://localhost:5000')
plants = r.json()
return render_template('index.html', plants=plants[:100])
if __name__ == '__main__':
app.run(debug=True, port=8080)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
<table class="table table-striped">
<tr>
<th>Symbol</th>
<th>Synonym Symbol</th>
<th>Scientific Name with Author</th>
<th>Common Name</th>
<th>Family</th>
</tr>
{% for plant in plants %}
<tr>
<td>{{ plant['Symbol'] }}</td>
<td>{{ plant['Synonym Symbol'] }}</td>
<td>{{ plant['Scientific Name with Author'] }}</td>
<td>{{ plant['Common Name'] }}</td>
<td>{{ plant['Family'] }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
Sprawdzenie czy działa jak należy

Komentarze
- Może się pojawić pytanie: dlaczego by nie uruchomić klienta MongoDB w projekcie frontend? Nie trzeba by dodatkowo opakowywać danych w format JSON, ani tworzyć kolejnego komponentu backend
- Taki projekt jak powyżej ma bardzo ważną zaletę. Jeżeli zechcemy nagle pobierać dane z bazy SQL albo nawet bezpośrednio z pliku, to musielibyśmy zmieniać kod frontendu
- W powyższym projekcie, frontend wykorzystuje stałe API, a źródło danych może być dowolnie podmieniane o ile backend je obsługujący będzie w stanie generować dane zgodne z API