diff --git a/Exam/Dockerfile b/Exam/Dockerfile
new file mode 100644
index 0000000..4e005b9
--- /dev/null
+++ b/Exam/Dockerfile
@@ -0,0 +1,15 @@
+# Dockerfile
+FROM nginx:alpine
+
+# Remove default content
+RUN rm -rf /usr/share/nginx/html/*
+
+# Copy your simulator files
+COPY . /usr/share/nginx/html
+
+# Expose port 80
+EXPOSE 80
+
+# Run Nginx in foreground
+CMD ["nginx", "-g", "daemon off;"]
+
diff --git a/Exam/Exam/Dockerfile b/Exam/Exam/Dockerfile
new file mode 100644
index 0000000..4e005b9
--- /dev/null
+++ b/Exam/Exam/Dockerfile
@@ -0,0 +1,15 @@
+# Dockerfile
+FROM nginx:alpine
+
+# Remove default content
+RUN rm -rf /usr/share/nginx/html/*
+
+# Copy your simulator files
+COPY . /usr/share/nginx/html
+
+# Expose port 80
+EXPOSE 80
+
+# Run Nginx in foreground
+CMD ["nginx", "-g", "daemon off;"]
+
diff --git a/Exam/disable-maintenance.sh b/Exam/disable-maintenance.sh
new file mode 100755
index 0000000..12e80ef
--- /dev/null
+++ b/Exam/disable-maintenance.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+set -e
+# deploy the real site back
+netlify deploy --prod --dir=. \
+ --message="✅ Live site ON"
+
diff --git a/Exam/docker-compose.yml b/Exam/docker-compose.yml
new file mode 100644
index 0000000..a04527d
--- /dev/null
+++ b/Exam/docker-compose.yml
@@ -0,0 +1,14 @@
+services:
+ simulator:
+ build: .
+ image: karel-simulator
+ container_name: karel-simulator
+ ports:
+ - "8080:80"
+ restart: unless-stopped
+
+ redis:
+ image: redis:alpine
+ container_name: karel-redis
+ restart: unless-stopped
+
diff --git a/Exam/enable-maintenance.sh b/Exam/enable-maintenance.sh
new file mode 100755
index 0000000..2269861
--- /dev/null
+++ b/Exam/enable-maintenance.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+set -e
+# deploy the maintenance folder
+netlify deploy --prod --dir=maintenance \
+ --message="⚙️ Maintenance page ON"
+
diff --git a/Exam/index.html b/Exam/index.html
new file mode 100755
index 0000000..d1f9838
--- /dev/null
+++ b/Exam/index.html
@@ -0,0 +1,849 @@
+
+
+
+
+ Karel Simulator
+
+
+
+ Karel Simulator
+
+
+
+
+
+ Write your Karel program below. Parentheses & semicolons mandatory.
+ If you’re ever unsure how to use the Simulator,
+
+ consult the manual
+ .
+
+
+
Compile & Run
+
Stop
+
Edit Map
+
Console Output:
+
+
Upload Map File:
+
+
Upload Map
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Exam/maintenance/index.html b/Exam/maintenance/index.html
new file mode 100644
index 0000000..222a280
--- /dev/null
+++ b/Exam/maintenance/index.html
@@ -0,0 +1,10 @@
+
+
+
+Down for Maintenance
+
+ ⚙️ Site Under Maintenance
+ We’ll be back shortly. Thank you for your patience!
+
+
+
diff --git a/Exam/manual.html b/Exam/manual.html
new file mode 100755
index 0000000..ae50aef
--- /dev/null
+++ b/Exam/manual.html
@@ -0,0 +1,106 @@
+
+
+
+
+ Karel Simulator — User Manual
+
+
+
+ Karel the Robot – Quick-Start User Guide
+
+ 1. What Is Karel?
+
+ Karel lives in a 2-D grid (“world”) of square cells.
+ He can face North/East/South/West, move one cell at a time,
+ pick up or put down “beepers,” and detect walls.
+
+
+ 2. Simulator Interface
+
+ Code Editor : Write your program here.
+ Compile & Run : Lex, parse, and execute step-by-step.
+ Stop : Immediately halt execution (for infinite loops).
+ Console : Logs moves, errors, and debug messages.
+ Upload Map : Load a .txt
or .kw
world file.
+ Map View : ASCII display of walls (red), beepers, and Karel (green).
+ Manual Editor : Draw your own world, then import it.
+
+
+ 3. Syntax Essentials
+
+ Every statement ends with a semicolon ;
.
+ Every command or condition must have parentheses ()
.
+ Use if (…){…} [else{…}]
and while (…){…}
.
+ Comments begin with //
.
+
+
+ 4. Built-in Commands
+ Movement
+
+ Command Effect
+ move()
Step forward if no wall ahead.
+ turnLeft()
Rotate 90° counter-clockwise.
+
+
+ Beeper Handling
+
+ Command Effect
+ pickBeeper()
Pick one beeper from current cell.
+ putBeeper()
Place one beeper into current cell.
+
+
+ Sensors & Conditions
+
+ Condition True When…
+ frontIsClear()
No wall immediately in front.
+ frontIsBlocked()
Wall immediately in front.
+ leftIsClear()
No wall on Karel’s left.
+ leftIsBlocked()
Wall on Karel’s left.
+ rightIsClear()
No wall on Karel’s right.
+ rightIsBlocked()
Wall on Karel’s right.
+ nextToABeeper()
One or more beepers in this cell.
+ notNextToABeeper()
No beepers in this cell.
+ facingNorth()
, facingEast()
, …
+ Karel’s orientation matches the named direction.
+ anyBeepersInBeeperBag()
Bag contains ≥ 1 beeper.
+ noBeepersInBeeperBag()
Bag is empty.
+
+
+ 5. Example
+ while ( notNextToABeeper() ) {
+ move();
+}
+pickBeeper();
+turnLeft();
+move();
+putBeeper();
+
+ 6. Tips
+
+ Sketch Karel’s path on graph paper first.
+ Always check frontIsClear()
before move()
.
+ Use the Stop button to escape accidental infinite loops.
+ Combine if
and while
for complex behaviors.
+
+
+ ← Back to Simulator
+
+
diff --git a/Exam/prepare-app.sh b/Exam/prepare-app.sh
new file mode 100755
index 0000000..0c7df7c
--- /dev/null
+++ b/Exam/prepare-app.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+set -e
+
+# Name for the Docker image
+IMAGE_NAME="karel-simulator"
+
+echo "🔨 Building Docker image '$IMAGE_NAME'..."
+docker build -t "${IMAGE_NAME}" .
+echo "✅ Image '${IMAGE_NAME}' built."
diff --git a/Exam/remove-app.sh b/Exam/remove-app.sh
new file mode 100755
index 0000000..d0280dc
--- /dev/null
+++ b/Exam/remove-app.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+set -e
+
+IMAGE_NAME="karel-simulator"
+CONTAINER_NAME="karel-simulator"
+
+# Stop & remove the container if it exists
+if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}\$"; then
+ echo "🗑️ Removing container '${CONTAINER_NAME}'..."
+ docker rm -f "${CONTAINER_NAME}"
+ echo "✅ Container removed."
+else
+ echo "ℹ️ No container named '${CONTAINER_NAME}' to remove."
+fi
+
+# Remove the image if it exists
+if docker images -q "${IMAGE_NAME}" >/dev/null; then
+ echo "🗑️ Removing image '${IMAGE_NAME}'..."
+ docker rmi "${IMAGE_NAME}"
+ echo "✅ Image removed."
+else
+ echo "ℹ️ No image named '${IMAGE_NAME}' to remove."
+fi
+
diff --git a/Exam/start-app.sh b/Exam/start-app.sh
new file mode 100755
index 0000000..b0c7d93
--- /dev/null
+++ b/Exam/start-app.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+set -e
+
+# 1) Clean up any existing containers (manual or compose)
+for NAME in karel-simulator karel-redis; do
+ if docker ps -a --format '{{.Names}}' | grep -q "^${NAME}\$"; then
+ echo "🛑 Removing existing container '${NAME}'..."
+ docker rm -f "${NAME}" >/dev/null 2>&1 || true
+ fi
+done
+
+# 2) (Re)start both services in detached mode
+echo "🚀 Starting multi-container application..."
+docker compose up -d
+
+# 3) Status
+echo "✅ All containers are up:"
+docker ps --filter "name=karel" --format " • {{.Names}} ({{.Image}}) → {{.Ports}}"
+echo ""
+echo "🌐 Simulator: http://localhost:8080/"
diff --git a/Exam/stop-app.sh b/Exam/stop-app.sh
new file mode 100755
index 0000000..9d4cb3a
--- /dev/null
+++ b/Exam/stop-app.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+set -e
+echo "⏹ Shutting down all containers..."
+docker-compose down
+echo "✅ Stopped."
diff --git a/assignment1/README.md b/assignment1/README.md
new file mode 100644
index 0000000..26f8774
--- /dev/null
+++ b/assignment1/README.md
@@ -0,0 +1,64 @@
+# Docker Web Application Deployment
+
+The application consists of two services:
+
+1. **Web Service (Nginx):**
+ - Uses the official Nginx image.
+ - Listens on port 80 inside the container and is mapped to host port 8080.
+2. **Database Service (MySQL 5.7):**
+ - Uses the official MySQL 5.7 image.
+ - Configured with a root password and a default database.
+ - Persists its data using the named volume `mysql-data`.
+
+## Files Overview
+
+- **prepare-app.sh:**
+ - Creates the required Docker network (`myapp-net`) and persistent volume (`mysql-data`).
+- **docker-compose.yaml:**
+ - Defines the two services along with their ports, environment variables, volumes, and restart policies.
+- **start-app.sh:**
+ - Starts the services using Docker Compose in detached mode.
+ - Displays the URL to access the web service.
+- **stop-app.sh:**
+ - Stops the running containers without deleting the persistent volume.
+- **remove-app.sh:**
+ - Removes all the created resources (containers, network, and volume) from the deployment.
+
+## Deployment Instructions
+
+1. **Preparation:**
+ - Ensure Docker and Docker Compose are installed.
+ - Make the scripts executable:
+ ```bash
+ chmod +x prepare-app.sh start-app.sh stop-app.sh remove-app.sh
+ ```
+ - Run the preparation script:
+ ```bash
+ ./prepare-app.sh
+ ```
+
+2. **Starting the Application:**
+ - Launch the services by running:
+ ```bash
+ ./start-app.sh
+ ```
+ - Open your web browser and navigate to [http://localhost:8080](http://localhost:8080) to see the Nginx welcome page.
+
+3. **Stopping the Application:**
+ - Stop the services without losing data:
+ ```bash
+ ./stop-app.sh
+ ```
+
+4. **Removing the Application:**
+ - To completely remove all deployed resources, run:
+ ```bash
+ ./remove-app.sh
+ ```
+
+## Notes
+
+- The application uses an external network (`myapp-net`) and a persistent volume (`mysql-data`) that are created in `prepare-app.sh`.
+- The Nginx container depends on the MySQL container to demonstrate inter-service communication within the `myapp-net` network.
+- Containers are configured to restart on failure.
+
diff --git a/assignment1/docker-compose.yaml b/assignment1/docker-compose.yaml
new file mode 100644
index 0000000..09426fa
--- /dev/null
+++ b/assignment1/docker-compose.yaml
@@ -0,0 +1,32 @@
+version: '3.8'
+
+services:
+ web:
+ image: nginx:latest
+ ports:
+ - "8080:80"
+ networks:
+ - myapp-net
+ restart: on-failure
+ depends_on:
+ - db
+
+ db:
+ image: mysql:5.7
+ environment:
+ MYSQL_ROOT_PASSWORD: example
+ MYSQL_DATABASE: appdb
+ volumes:
+ - mysql-data:/var/lib/mysql
+ networks:
+ - myapp-net
+ restart: on-failure
+
+networks:
+ myapp-net:
+ external: true
+
+volumes:
+ mysql-data:
+ external: true
+
diff --git a/assignment1/prepare-app.sh b/assignment1/prepare-app.sh
new file mode 100755
index 0000000..753d306
--- /dev/null
+++ b/assignment1/prepare-app.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# prepare-app.sh
+
+if ! docker network ls | grep -w myapp-net >/dev/null; then
+ docker network create myapp-net
+ echo "Created Docker network: myapp-net"
+else
+ echo "Docker network myapp-net already exists."
+fi
+
+
+if ! docker volume ls | grep -w mysql-data >/dev/null; then
+ docker volume create mysql-data
+ echo "Created Docker volume: mysql-data"
+else
+ echo "Docker volume mysql-data already exists."
+fi
+
+echo "Preparation complete."
+
diff --git a/assignment1/remove-app.sh b/assignment1/remove-app.sh
new file mode 100755
index 0000000..3aa3114
--- /dev/null
+++ b/assignment1/remove-app.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+# remove-app.sh
+
+docker-compose down
+
+docker volume rm mysql-data
+docker network rm myapp-net
+
+echo "All application resources removed."
+
diff --git a/assignment1/start-app.sh b/assignment1/start-app.sh
new file mode 100755
index 0000000..5be746e
--- /dev/null
+++ b/assignment1/start-app.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+# start-app.sh
+
+docker-compose up -d
+
+sleep 5
+
+echo "Application started. Access the web service at http://localhost:8080"
+
diff --git a/assignment1/stop-app.sh b/assignment1/stop-app.sh
new file mode 100755
index 0000000..d4db2c2
--- /dev/null
+++ b/assignment1/stop-app.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# stop-app.sh
+
+docker-compose stop
+echo "Application services stopped. Persistent data remains intact."
+
diff --git a/assignment2/.prepare-app.sh.swp b/assignment2/.prepare-app.sh.swp
new file mode 100644
index 0000000..5a49185
Binary files /dev/null and b/assignment2/.prepare-app.sh.swp differ
diff --git a/assignment2/Dockerfile b/assignment2/Dockerfile
new file mode 100644
index 0000000..9955ee2
--- /dev/null
+++ b/assignment2/Dockerfile
@@ -0,0 +1,2 @@
+FROM nginx:alpine
+COPY weather.html /usr/share/nginx/html/index.html
diff --git a/assignment2/Dockerfile.api b/assignment2/Dockerfile.api
new file mode 100644
index 0000000..591ee9a
--- /dev/null
+++ b/assignment2/Dockerfile.api
@@ -0,0 +1,6 @@
+FROM node:18-alpine
+WORKDIR /app
+COPY server.js .
+RUN npm init -y && npm install express pg body-parser
+EXPOSE 3000
+CMD ["node", "server.js"]
diff --git a/assignment2/README.md b/assignment2/README.md
new file mode 100644
index 0000000..7669725
--- /dev/null
+++ b/assignment2/README.md
@@ -0,0 +1,170 @@
+# Weather Web App - Kubernetes Deployment
+
+This project deploys a full-stack weather web application to Kubernetes. It includes:
+- A frontend website to search weather by city
+- A backend PostgreSQL database for logging searches
+- A Node.js API to connect the frontend to the database
+
+---
+
+## Application Description
+
+- **Frontend (weather.html):** A responsive, modern web UI that shows current weather data using the OpenWeatherMap API.
+- **Backend (PostgreSQL):** Stores weather search history via a `weather_log` table.
+- **API Server (Node.js):** Receives weather data from the frontend and logs it to the PostgreSQL database.
+
+---
+
+## Containers Used
+
+| Container | Image | Description |
+|------------------|--------------------|----------------------------------------------|
+| `weather-frontend` | Custom Nginx-based | Serves the `weather.html` UI |
+| `postgres` | `postgres:15` | Provides relational database backend |
+| `weather-api` | Custom Node.js | API that logs weather data to PostgreSQL |
+
+---
+
+## ☸️ Kubernetes Objects
+
+| Object Type | File | Description |
+|------------------------|------------------------|----------------------------------------------------------------------|
+| `Namespace` | (inside script) | Isolates resources under `webapp-ns` |
+| `Deployment` | `deployment.yaml` | Manages frontend app |
+| `Deployment` | `deployment-api.yaml` | Manages the Node.js API |
+| `StatefulSet` | `statefulset.yaml` | Manages PostgreSQL instance with persistent volume |
+| `PersistentVolume` | `statefulset.yaml` | Host-mounted volume for PostgreSQL data |
+| `PersistentVolumeClaim`| `statefulset.yaml` | Requests storage for StatefulSet |
+| `Service` | `service.yaml` | Exposes frontend via NodePort |
+| `Service` | `deployment-api.yaml` | Exposes API via NodePort |
+| `Service` | `postgres-service.yaml`| Internal ClusterIP service for PostgreSQL DNS resolution |
+| `ConfigMap` | `db-init-script` | Stores the SQL init script for table creation |
+
+---
+
+## Networking & Volumes
+
+### Virtual Networks:
+- Kubernetes services provide internal DNS for `postgres` and `weather-api-service`.
+- Frontend and API exposed externally using `NodePort` services.
+
+### Volumes:
+- `PersistentVolume` and `PersistentVolumeClaim` ensure PostgreSQL data is retained.
+- `ConfigMap` used to apply `init-db.sql` manually via `psql`.
+
+---
+
+## ⚙️ Container Configurations
+
+### Frontend
+- Dockerfile uses `nginx:alpine`
+- Serves `weather.html`
+- Exposed on port `80`
+
+### Node.js API
+- Built with Node.js 18
+- Listens on port `3000`
+- Connects to PostgreSQL using service DNS `postgres`
+- Accepts POST requests at `/log`
+
+### PostgreSQL
+- `postgres:15` with `weatheruser`, `weatherpass`, and `weatherdb`
+- Table `weather_log` is created manually after StatefulSet starts
+
+---
+
+## How to Use the Application
+
+### 1. Build Docker Images
+
+```bash
+./prepare-app.sh
+```
+
+### 2. Start the App (create namespace and apply all configs)
+
+```bash
+./start-app.sh
+```
+
+### 3. Manually Initialize the Database
+
+```bash
+kubectl exec -it -n webapp-ns statefulset/postgres -- psql -U weatheruser -d weatherdb
+```
+
+Paste this inside the prompt:
+
+```sql
+CREATE TABLE IF NOT EXISTS weather_log (
+ id SERIAL PRIMARY KEY,
+ city VARCHAR(100),
+ temperature DECIMAL(5,2),
+ description TEXT,
+ timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+```
+
+Exit with:
+```sql
+\q
+```
+
+### 4. View the App
+
+```bash
+minikube service weather-service -n webapp-ns
+```
+
+Or manually:
+
+```bash
+minikube ip
+kubectl get svc -n webapp-ns
+```
+Then open:
+```
+http://:
+```
+
+### 5. Use the App
+- Search for a city
+- Weather appears
+- Weather data is logged via API to PostgreSQL
+
+### 6. View Logged Data
+
+```bash
+kubectl exec -it -n webapp-ns statefulset/postgres -- psql -U weatheruser -d weatherdb
+```
+
+```sql
+SELECT * FROM weather_log ORDER BY timestamp DESC;
+```
+
+### 7. Stop and Clean Up
+
+```bash
+./stop-app.sh
+```
+
+---
+
+## API Key Setup
+
+- Register at [OpenWeatherMap](https://openweathermap.org/api)
+- Replace the key in `weather.html`:
+
+```js
+const apiKey = "YOUR_API_KEY";
+```
+
+---
+
+## Conclusion
+
+- Frontend fetches real-time weather from OpenWeatherMap
+- Logs are POSTed to backend and stored in PostgreSQL
+
+---
+
diff --git a/assignment2/deployment-api.yaml b/assignment2/deployment-api.yaml
new file mode 100644
index 0000000..ef0c51e
--- /dev/null
+++ b/assignment2/deployment-api.yaml
@@ -0,0 +1,41 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: weather-api
+ namespace: webapp-ns
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: weather-api
+ template:
+ metadata:
+ labels:
+ app: weather-api
+ spec:
+ initContainers:
+ - name: wait-for-postgres
+ image: busybox
+ command: ['sh', '-c', 'until nslookup postgres; do echo waiting for db; sleep 2; done']
+ containers:
+ - name: weather-api
+ image: weather-api:latest
+ imagePullPolicy: IfNotPresent
+ ports:
+ - containerPort: 3000
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: weather-api-service
+ namespace: webapp-ns
+spec:
+ selector:
+ app: weather-api
+ ports:
+ - protocol: TCP
+ port: 3000
+ targetPort: 3000
+ nodePort: 31000
+ type: NodePort
+
diff --git a/assignment2/deployment.yaml b/assignment2/deployment.yaml
new file mode 100644
index 0000000..de11dfa
--- /dev/null
+++ b/assignment2/deployment.yaml
@@ -0,0 +1,22 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: weather-frontend
+ namespace: webapp-ns
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: weather-frontend
+ template:
+ metadata:
+ labels:
+ app: weather-frontend
+ spec:
+ containers:
+ - name: weather-frontend
+ image: weather-frontend:latest
+ imagePullPolicy: IfNotPresent
+ ports:
+ - containerPort: 80
+
diff --git a/assignment2/init-db.sql b/assignment2/init-db.sql
new file mode 100644
index 0000000..8835f65
--- /dev/null
+++ b/assignment2/init-db.sql
@@ -0,0 +1,11 @@
+CREATE TABLE IF NOT EXISTS weather_log (
+ id SERIAL PRIMARY KEY,
+ city VARCHAR(100),
+ temperature DECIMAL(5,2),
+ description TEXT,
+ timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+INSERT INTO weather_log (city, temperature, description)
+VALUES ('London', 15.5, 'partly cloudy');
+
diff --git a/assignment2/inti-db.sql b/assignment2/inti-db.sql
new file mode 100644
index 0000000..e69de29
diff --git a/assignment2/minikube-linux-amd64 b/assignment2/minikube-linux-amd64
new file mode 100644
index 0000000..af25bb2
Binary files /dev/null and b/assignment2/minikube-linux-amd64 differ
diff --git a/assignment2/postgres-service.yaml b/assignment2/postgres-service.yaml
new file mode 100644
index 0000000..0622926
--- /dev/null
+++ b/assignment2/postgres-service.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: postgres
+ namespace: webapp-ns
+spec:
+ selector:
+ app: postgres
+ ports:
+ - protocol: TCP
+ port: 5432
+ targetPort: 5432
+
diff --git a/assignment2/prepare-app.sh b/assignment2/prepare-app.sh
new file mode 100755
index 0000000..21d38f9
--- /dev/null
+++ b/assignment2/prepare-app.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+IMAGE_NAME=weather-frontend
+IMAGE_TAG=lates
+
+echo "🔧 Building Docker image: $IMAGE_NAME:$IMAGE_TAG"
+docker build -t $IMAGE_NAME:$IMAGE_TAG .
+docker build -t weather-api:latest -f Dockerfile.api .
+
+echo "✅ Build complete."
+
diff --git a/assignment2/server.js b/assignment2/server.js
new file mode 100644
index 0000000..2101596
--- /dev/null
+++ b/assignment2/server.js
@@ -0,0 +1,35 @@
+const express = require('express');
+const bodyParser = require('body-parser');
+const { Pool } = require('pg');
+
+const app = express();
+const port = 3000;
+
+app.use(bodyParser.json());
+
+const pool = new Pool({
+ host: 'postgres',
+ user: 'weatheruser',
+ password: 'weatherpass',
+ database: 'weatherdb',
+ port: 5432
+});
+
+app.post('/log', async (req, res) => {
+ const { city, temperature, description } = req.body;
+ try {
+ await pool.query(
+ 'INSERT INTO weather_log (city, temperature, description) VALUES ($1, $2, $3)',
+ [city, temperature, description]
+ );
+ res.status(200).send('Logged!');
+ } catch (err) {
+ console.error(err);
+ res.status(500).send('Error saving data');
+ }
+});
+
+app.listen(port, () => {
+ console.log(`Weather API listening on port ${port}`);
+});
+
diff --git a/assignment2/service.yaml b/assignment2/service.yaml
new file mode 100644
index 0000000..96f3ffd
--- /dev/null
+++ b/assignment2/service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: weather-service
+ namespace: webapp-ns
+spec:
+ selector:
+ app: weather-frontend
+ ports:
+ - protocol: TCP
+ port: 80
+ targetPort: 80
+ type: NodePort
+
diff --git a/assignment2/start-app.sh b/assignment2/start-app.sh
new file mode 100755
index 0000000..cf5a3b9
--- /dev/null
+++ b/assignment2/start-app.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+echo "🚀 Creating namespace 'webapp-ns'..."
+kubectl create namespace webapp-ns
+
+echo "📦 Deploying frontend app..."
+kubectl apply -f deployment.yaml
+kubectl apply -f service.yaml
+
+echo "🧾 Creating ConfigMap with init-db.sql..."
+kubectl create configmap db-init-script --from-file=init-db.sql=init-db.sql -n webapp-ns
+
+echo "🗄️ Deploying database backend..."
+kubectl apply -f statefulset.yaml
+kubectl apply -f deployment-api.yaml
+
+echo "✅ All resources created."
diff --git a/assignment2/statefulset.yaml b/assignment2/statefulset.yaml
new file mode 100644
index 0000000..081e54b
--- /dev/null
+++ b/assignment2/statefulset.yaml
@@ -0,0 +1,65 @@
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+ name: postgres-pv
+ namespace: webapp-ns
+spec:
+ capacity:
+ storage: 1Gi
+ accessModes:
+ - ReadWriteOnce
+ hostPath:
+ path: "/mnt/data/postgres"
+---
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: postgres-pvc
+ namespace: webapp-ns
+spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 1Gi
+---
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: postgres
+ namespace: webapp-ns
+spec:
+ serviceName: "postgres"
+ replicas: 1
+ selector:
+ matchLabels:
+ app: postgres
+ template:
+ metadata:
+ labels:
+ app: postgres
+ spec:
+ containers:
+ - name: postgres
+ image: postgres:15
+ ports:
+ - containerPort: 5432
+ env:
+ - name: POSTGRES_USER
+ value: "weatheruser"
+ - name: POSTGRES_PASSWORD
+ value: "weatherpass"
+ - name: POSTGRES_DB
+ value: "weatherdb"
+ volumeMounts:
+ - name: postgres-storage
+ mountPath: /var/lib/postgresql/data
+ volumeClaimTemplates:
+ - metadata:
+ name: postgres-storage
+ spec:
+ accessModes: ["ReadWriteOnce"]
+ resources:
+ requests:
+ storage: 1Gi
+
diff --git a/assignment2/stop-app.sh b/assignment2/stop-app.sh
new file mode 100755
index 0000000..19c58aa
--- /dev/null
+++ b/assignment2/stop-app.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+echo "🧼 Deleting all resources in namespace 'webapp-ns'..."
+kubectl delete namespace webapp-ns
+
+echo "✅ Cleanup complete."
+
diff --git a/assignment2/weather.html b/assignment2/weather.html
new file mode 100644
index 0000000..7dd0628
--- /dev/null
+++ b/assignment2/weather.html
@@ -0,0 +1,122 @@
+
+
+
+
+
+ Weather Info
+
+
+
+
+
+
🌦️ Check the Weather
+
+
Get Weather
+
+
+
+
+
+
+