281 lines
7.0 KiB
YAML
281 lines
7.0 KiB
YAML
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: postgres-service
|
|
namespace: z2app
|
|
spec:
|
|
selector:
|
|
app: postgres
|
|
ports:
|
|
- port: 5432
|
|
targetPort: 5432
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: backend-service
|
|
namespace: z2app
|
|
spec:
|
|
selector:
|
|
app: backend
|
|
ports:
|
|
- port: 5000
|
|
targetPort: 5000
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: frontend-service
|
|
namespace: z2app
|
|
spec:
|
|
type: NodePort
|
|
selector:
|
|
app: frontend
|
|
ports:
|
|
- port: 80
|
|
targetPort: 80
|
|
nodePort: 30080
|
|
---
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: frontend-html-config
|
|
namespace: z2app
|
|
data:
|
|
index.html: |
|
|
<!DOCTYPE html>
|
|
<html lang="es">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>Task Notes App</title>
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
background: #f4f6f8;
|
|
color: #222;
|
|
margin: 0;
|
|
padding: 40px;
|
|
}
|
|
.container {
|
|
max-width: 700px;
|
|
margin: 0 auto;
|
|
background: white;
|
|
padding: 30px;
|
|
border-radius: 12px;
|
|
box-shadow: 0 4px 14px rgba(0,0,0,0.1);
|
|
}
|
|
h1 { margin-top: 0; }
|
|
.row {
|
|
display: flex;
|
|
gap: 10px;
|
|
margin-bottom: 20px;
|
|
}
|
|
input {
|
|
flex: 1;
|
|
padding: 12px;
|
|
border: 1px solid #ccc;
|
|
border-radius: 8px;
|
|
font-size: 16px;
|
|
}
|
|
button {
|
|
padding: 12px 16px;
|
|
border: none;
|
|
border-radius: 8px;
|
|
cursor: pointer;
|
|
background: #2563eb;
|
|
color: white;
|
|
font-size: 15px;
|
|
}
|
|
button.delete {
|
|
background: #dc2626;
|
|
}
|
|
ul {
|
|
list-style: none;
|
|
padding: 0;
|
|
}
|
|
li {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 12px;
|
|
border: 1px solid #e5e7eb;
|
|
border-radius: 8px;
|
|
margin-bottom: 10px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1>Task Notes App</h1>
|
|
<p>Simple notes/tasks app running on Kubernetes.</p>
|
|
<div class="row">
|
|
<input id="taskInput" type="text" placeholder="Write a task or note..." />
|
|
<button onclick="addTask()">Add</button>
|
|
</div>
|
|
<ul id="taskList"></ul>
|
|
</div>
|
|
|
|
<script>
|
|
async function loadTasks() {
|
|
const res = await fetch('/api/tasks');
|
|
const tasks = await res.json();
|
|
const list = document.getElementById('taskList');
|
|
list.innerHTML = '';
|
|
|
|
tasks.forEach(task => {
|
|
const li = document.createElement('li');
|
|
li.innerHTML = `
|
|
<span>${task.text}</span>
|
|
<button class="delete" onclick="deleteTask(${task.id})">Delete</button>
|
|
`;
|
|
list.appendChild(li);
|
|
});
|
|
}
|
|
|
|
async function addTask() {
|
|
const input = document.getElementById('taskInput');
|
|
const text = input.value.trim();
|
|
if (!text) return;
|
|
|
|
await fetch('/api/tasks', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ text })
|
|
});
|
|
|
|
input.value = '';
|
|
loadTasks();
|
|
}
|
|
|
|
async function deleteTask(id) {
|
|
await fetch('/api/tasks/' + id, { method: 'DELETE' });
|
|
loadTasks();
|
|
}
|
|
|
|
loadTasks();
|
|
</script>
|
|
</body>
|
|
</html>
|
|
---
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: frontend-nginx-config
|
|
namespace: z2app
|
|
data:
|
|
default.conf: |
|
|
server {
|
|
listen 80;
|
|
server_name localhost;
|
|
|
|
location / {
|
|
root /usr/share/nginx/html;
|
|
index index.html;
|
|
try_files $uri $uri/ /index.html;
|
|
}
|
|
|
|
location /api/ {
|
|
proxy_pass http://backend-service:5000/;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
}
|
|
}
|
|
---
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: backend-code-config
|
|
namespace: z2app
|
|
data:
|
|
app.py: |
|
|
import os
|
|
import psycopg2
|
|
from flask import Flask, request, jsonify
|
|
|
|
app = Flask(__name__)
|
|
|
|
DB_HOST = os.getenv("DB_HOST", "postgres-service")
|
|
DB_PORT = os.getenv("DB_PORT", "5432")
|
|
DB_NAME = os.getenv("DB_NAME", "appdb")
|
|
DB_USER = os.getenv("DB_USER", "appuser")
|
|
DB_PASSWORD = os.getenv("DB_PASSWORD", "apppass")
|
|
|
|
def get_conn():
|
|
return psycopg2.connect(
|
|
host=DB_HOST,
|
|
port=DB_PORT,
|
|
dbname=DB_NAME,
|
|
user=DB_USER,
|
|
password=DB_PASSWORD
|
|
)
|
|
|
|
def init_db():
|
|
conn = get_conn()
|
|
cur = conn.cursor()
|
|
cur.execute("""
|
|
CREATE TABLE IF NOT EXISTS tasks (
|
|
id SERIAL PRIMARY KEY,
|
|
text TEXT NOT NULL
|
|
)
|
|
""")
|
|
conn.commit()
|
|
cur.close()
|
|
conn.close()
|
|
|
|
@app.after_request
|
|
def add_cors_headers(response):
|
|
response.headers["Access-Control-Allow-Origin"] = "*"
|
|
response.headers["Access-Control-Allow-Headers"] = "Content-Type"
|
|
response.headers["Access-Control-Allow-Methods"] = "GET,POST,DELETE,OPTIONS"
|
|
return response
|
|
|
|
@app.route("/")
|
|
def home():
|
|
return "Backend is running"
|
|
|
|
@app.route("/health")
|
|
def health():
|
|
return {"status": "ok"}
|
|
|
|
@app.route("/tasks", methods=["GET"])
|
|
def get_tasks():
|
|
conn = get_conn()
|
|
cur = conn.cursor()
|
|
cur.execute("SELECT id, text FROM tasks ORDER BY id DESC")
|
|
rows = cur.fetchall()
|
|
cur.close()
|
|
conn.close()
|
|
return jsonify([{"id": r[0], "text": r[1]} for r in rows])
|
|
|
|
@app.route("/tasks", methods=["POST"])
|
|
def create_task():
|
|
data = request.get_json()
|
|
text = data.get("text", "").strip()
|
|
|
|
if not text:
|
|
return jsonify({"error": "Text is required"}), 400
|
|
|
|
conn = get_conn()
|
|
cur = conn.cursor()
|
|
cur.execute("INSERT INTO tasks (text) VALUES (%s) RETURNING id", (text,))
|
|
new_id = cur.fetchone()[0]
|
|
conn.commit()
|
|
cur.close()
|
|
conn.close()
|
|
|
|
return jsonify({"id": new_id, "text": text}), 201
|
|
|
|
@app.route("/tasks/<int:task_id>", methods=["DELETE"])
|
|
def delete_task(task_id):
|
|
conn = get_conn()
|
|
cur = conn.cursor()
|
|
cur.execute("DELETE FROM tasks WHERE id = %s", (task_id,))
|
|
conn.commit()
|
|
cur.close()
|
|
conn.close()
|
|
return jsonify({"deleted": task_id})
|
|
|
|
if __name__ == "__main__":
|
|
init_db()
|
|
app.run(host="0.0.0.0", port=5000) |