update example
parent
6535670cd3
commit
fee6fdec2b
15
Dockerfile
15
Dockerfile
|
|
@ -1,8 +1,11 @@
|
|||
FROM python:3.11-slim
|
||||
|
||||
# Install gcc compiler for C code compilation
|
||||
# Create a non-root user for security
|
||||
RUN useradd --create-home --shell /bin/bash app
|
||||
|
||||
# Install gcc compiler for C code compilation and other production dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y gcc build-essential && \
|
||||
apt-get install -y gcc build-essential curl && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Set working directory
|
||||
|
|
@ -15,8 +18,12 @@ RUN pip install --no-cache-dir -r requirements.txt
|
|||
# Copy application code
|
||||
COPY . .
|
||||
|
||||
# Change ownership to the app user
|
||||
RUN chown -R app:app /app
|
||||
USER app
|
||||
|
||||
# Expose port 5000
|
||||
EXPOSE 5000
|
||||
|
||||
# Run the application with Gunicorn
|
||||
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "1", "app:app"]
|
||||
# Run the application with Gunicorn in production mode using config file
|
||||
CMD ["gunicorn", "--config", "gunicorn.conf.py", "app:app"]
|
||||
185
README.md
185
README.md
|
|
@ -70,6 +70,38 @@ The system uses Markdown files for content management. There are two main types
|
|||
|
||||
The content directory is located at the parent directory level, outside of the `elemes/` directory. This allows for easy linking and sharing of content between different instances of the LMS.
|
||||
|
||||
### Environment Configuration
|
||||
|
||||
The application uses environment variables for configuration. Create a `.env` file at the parent directory level (same level as the `elemes/` directory) to configure the application. The `podman-compose.yml` file is configured to read environment variables from `../.env`.
|
||||
|
||||
Example `.env` file:
|
||||
```
|
||||
# Production Environment Configuration
|
||||
|
||||
# Flask Configuration
|
||||
FLASK_ENV=production
|
||||
FLASK_DEBUG=0
|
||||
SECRET_KEY=your-super-secret-key-here-change-this-in-production
|
||||
|
||||
# Application Configuration
|
||||
CONTENT_DIR=content
|
||||
STATIC_DIR=static
|
||||
TEMPLATES_DIR=templates
|
||||
TOKENS_FILE=tokens.csv
|
||||
|
||||
# Server Configuration
|
||||
HOST=0.0.0.0
|
||||
PORT=5000
|
||||
|
||||
# Security Configuration
|
||||
MAX_CONTENT_LENGTH=1024 * 1024 # 1MB max upload size
|
||||
WTF_CSRF_ENABLED=true
|
||||
|
||||
# Logging Configuration
|
||||
LOG_LEVEL=INFO
|
||||
LOG_FILE=/var/log/lms-c/app.log
|
||||
```
|
||||
|
||||
### Home Page (`home.md`)
|
||||
|
||||
The home page serves as the main landing page and lesson directory. Here's the template structure:
|
||||
|
|
@ -392,13 +424,121 @@ This LMS can be used as a submodule in another repository. To set it up:
|
|||
|
||||
3. Add your lesson files to the content directory
|
||||
|
||||
4. Run the LMS from the elemes directory:
|
||||
4. Create an environment configuration file at the root level:
|
||||
```bash
|
||||
touch .env
|
||||
```
|
||||
|
||||
5. Run the LMS from the elemes directory:
|
||||
```bash
|
||||
cd elemes
|
||||
podman-compose -f podman-compose.yml up --build
|
||||
```
|
||||
|
||||
The content directory at the root level will be automatically mounted to the application container.
|
||||
The content directory and environment configuration at the root level will be automatically mounted to the application container.
|
||||
|
||||
## Production Deployment
|
||||
|
||||
For production deployment, additional considerations and configurations are required to ensure security, performance, and reliability.
|
||||
|
||||
### Production Environment Setup
|
||||
|
||||
1. **Environment Variables**: Use the following environment variables for production:
|
||||
- `FLASK_ENV=production` - Sets the environment to production
|
||||
- `FLASK_DEBUG=0` - Disables debug mode
|
||||
- `PORT=5000` - Specifies the port to run the application on
|
||||
|
||||
2. **Security Considerations**:
|
||||
- Run the container as a non-root user (already configured in Dockerfile)
|
||||
- Limit resource usage with podman/docker resource constraints
|
||||
- Use a reverse proxy (like Nginx) in front of the application
|
||||
- Implement proper HTTPS with SSL/TLS certificates
|
||||
|
||||
3. **Performance Optimizations**:
|
||||
- Use the multi-worker Gunicorn configuration (already configured)
|
||||
- Set appropriate worker processes based on your server's CPU cores
|
||||
- Configure proper caching mechanisms if needed
|
||||
|
||||
### Production Deployment with Podman
|
||||
|
||||
To deploy in a production environment:
|
||||
|
||||
1. Build the production image:
|
||||
```bash
|
||||
podman build -t lms-c:prod .
|
||||
```
|
||||
|
||||
2. Run with production settings:
|
||||
```bash
|
||||
podman run -d \
|
||||
--name lms-c-prod \
|
||||
-p 80:5000 \
|
||||
-v /path/to/production/content:/app/content \
|
||||
-v /path/to/production/static:/app/static \
|
||||
-v /path/to/production/tokens.csv:/app/tokens.csv \
|
||||
--restart=unless-stopped \
|
||||
--memory=512m \
|
||||
--cpus=1 \
|
||||
lms-c:prod
|
||||
```
|
||||
|
||||
### Production Deployment with Podman Compose
|
||||
|
||||
Create a production-specific compose file (`podman-compose.prod.yml`):
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
lms-c:
|
||||
build: .
|
||||
ports:
|
||||
- "80:5000"
|
||||
volumes:
|
||||
- /path/to/production/content:/app/content
|
||||
- /path/to/production/static:/app/static
|
||||
- /path/to/production/templates:/app/templates
|
||||
- /path/to/production/tokens.csv:/app/tokens.csv
|
||||
env_file:
|
||||
- /path/to/production/.env
|
||||
restart: unless-stopped
|
||||
mem_limit: 512m
|
||||
cpus: 1.0
|
||||
```
|
||||
|
||||
Run with:
|
||||
```bash
|
||||
podman-compose -f podman-compose.prod.yml up -d --build
|
||||
```
|
||||
|
||||
### Reverse Proxy Configuration
|
||||
|
||||
For production, it's recommended to put a reverse proxy like Nginx in front of the application:
|
||||
|
||||
Example Nginx configuration:
|
||||
```
|
||||
server {
|
||||
listen 80;
|
||||
server_name your-domain.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:5000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### SSL/HTTPS Setup
|
||||
|
||||
For HTTPS, you can use Let's Encrypt with Certbot:
|
||||
```bash
|
||||
sudo certbot --nginx -d your-domain.com
|
||||
```
|
||||
|
||||
This will automatically configure SSL certificates for your domain.
|
||||
|
||||
## Security Considerations
|
||||
|
||||
|
|
@ -416,8 +556,12 @@ The content directory at the root level will be automatically mounted to the app
|
|||
- `tokens.csv`: Student progress tracking file
|
||||
- `generate_tokens.py`: Script to generate tokens CSV file
|
||||
- `Dockerfile`: Container configuration
|
||||
- `podman-compose.yml`: Podman Compose configuration
|
||||
- `podman-compose.yml`: Podman Compose configuration with env_file support
|
||||
- `requirements.txt`: Python dependencies
|
||||
- `test/`: Directory containing test scripts and load testing tools
|
||||
- `test/test_production.sh`: Production environment test script
|
||||
- `test/locustfile.py`: Load testing script using Locust
|
||||
- `test/podman-compose.locust.yml`: Podman Compose configuration for load testing
|
||||
|
||||
## Development
|
||||
|
||||
|
|
@ -427,12 +571,27 @@ To access the running container for development:
|
|||
podman exec -it <container_name> /bin/bash
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
The project includes comprehensive test scripts:
|
||||
|
||||
1. **Production Environment Tests**: Run the production test script to verify all functionality:
|
||||
```bash
|
||||
./test/test_production.sh
|
||||
```
|
||||
|
||||
2. **Load Testing**: Use the included Locust configuration for load testing:
|
||||
```bash
|
||||
podman-compose -f test/podman-compose.locust.yml up --build
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- If you get permission errors, make sure your user has access to Podman
|
||||
- If the application doesn't start, check that port 5000 is available
|
||||
- If code compilation fails, verify that the gcc compiler is available in the container
|
||||
- If progress tracking isn't working, ensure the tokens.csv file is properly formatted
|
||||
- If environment variables aren't being loaded, verify that the .env file is in the correct location and properly formatted
|
||||
|
||||
## Stopping the Application
|
||||
|
||||
|
|
@ -562,11 +721,11 @@ The system includes support for load testing using Locust to simulate multiple c
|
|||
4. **Alternative: Run Locust Directly**
|
||||
- Install Locust on the load testing machine:
|
||||
```bash
|
||||
pip install -r locust/requirements.txt
|
||||
pip install -r test/requirements.txt
|
||||
```
|
||||
- Run Locust directly:
|
||||
```bash
|
||||
cd locust
|
||||
cd test
|
||||
locust -f locustfile.py --host http://<LMS_SERVER_IP>:5000
|
||||
```
|
||||
|
||||
|
|
@ -587,3 +746,19 @@ Monitor the LMS server's resource usage (CPU, memory, disk I/O) during load test
|
|||
- Compilation performance under load
|
||||
- Database performance (if one is added in the future)
|
||||
- Container resource limits
|
||||
|
||||
The included `locustfile.py` simulates the following user behaviors:
|
||||
- Browsing the home page
|
||||
- Viewing lessons
|
||||
- Compiling C code
|
||||
- Validating student tokens
|
||||
- Logging in with tokens
|
||||
- Tracking student progress
|
||||
|
||||
### Monitoring Performance
|
||||
|
||||
Monitor the LMS server's resource usage (CPU, memory, disk I/O) during load testing to identify potential bottlenecks. Pay attention to:
|
||||
- Response times for API requests
|
||||
- Compilation performance under load
|
||||
- Database performance (if one is added in the future)
|
||||
- Container resource limits
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ else
|
|||
podman exec -it lms-c-container /bin/bash
|
||||
else
|
||||
echo "Building and starting container..."
|
||||
podman build -t lms-c . && podman run -d -p 5000:5000 --name lms-c-container -v ../content:/app/content -v ./static:/app/static -v ./templates:/app/templates -v ./tokens.csv:/app/tokens.csv lms-c
|
||||
podman build -t lms-c . && podman run -d -p 5000:5000 --name lms-c-container -v ../content:/app/content -v ./static:/app/static -v ./templates:/app/templates -v ./tokens.csv:/app/tokens.csv -e FLASK_ENV=production -e FLASK_DEBUG=0 lms-c
|
||||
sleep 5 # Wait for the application to start
|
||||
podman exec -it lms-c-container /bin/bash
|
||||
fi
|
||||
|
|
|
|||
29
app.py
29
app.py
|
|
@ -9,6 +9,7 @@ import subprocess
|
|||
import tempfile
|
||||
import markdown
|
||||
from flask import Flask, render_template, request, jsonify, send_from_directory
|
||||
from flask_talisman import Talisman
|
||||
import glob
|
||||
import csv
|
||||
import uuid
|
||||
|
|
@ -16,11 +17,29 @@ from datetime import datetime
|
|||
|
||||
app = Flask(__name__)
|
||||
|
||||
# Configuration
|
||||
CONTENT_DIR = 'content'
|
||||
STATIC_DIR = 'static'
|
||||
TEMPLATES_DIR = 'templates'
|
||||
TOKENS_FILE = 'tokens.csv'
|
||||
# Load configuration from environment variables with defaults
|
||||
CONTENT_DIR = os.environ.get('CONTENT_DIR', 'content')
|
||||
STATIC_DIR = os.environ.get('STATIC_DIR', 'static')
|
||||
TEMPLATES_DIR = os.environ.get('TEMPLATES_DIR', 'templates')
|
||||
TOKENS_FILE = os.environ.get('TOKENS_FILE', 'tokens.csv')
|
||||
|
||||
# Security configuration using Talisman
|
||||
Talisman(app,
|
||||
force_https=False, # Set to True if using SSL
|
||||
strict_transport_security=True,
|
||||
strict_transport_security_max_age=31536000,
|
||||
frame_options='DENY',
|
||||
content_security_policy={
|
||||
'default-src': "'self'",
|
||||
'script-src': "'self' 'unsafe-inline' https://cdnjs.cloudflare.com",
|
||||
'style-src': "'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com",
|
||||
'img-src': "'self' data: https:",
|
||||
'font-src': "'self' https://cdn.jsdelivr.net",
|
||||
'connect-src': "'self'",
|
||||
'frame-ancestors': "'none'",
|
||||
},
|
||||
referrer_policy='strict-origin-when-cross-origin'
|
||||
)
|
||||
|
||||
def get_lessons():
|
||||
"""Get all lesson files from the content directory"""
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
# Production Environment Configuration
|
||||
#
|
||||
|
||||
# tailscale Configuration
|
||||
ELEMES_HOST=change-to-lms-topic
|
||||
TS_AUTHKEY=your-super-secret-key-here-change-this-in-production
|
||||
|
||||
# Flask Configuration
|
||||
FLASK_ENV=production
|
||||
FLASK_DEBUG=0
|
||||
SECRET_KEY=your-super-secret-key-here-change-this-in-production
|
||||
|
||||
# Application Configuration
|
||||
CONTENT_DIR=content
|
||||
STATIC_DIR=static
|
||||
TEMPLATES_DIR=templates
|
||||
TOKENS_FILE=tokens.csv
|
||||
|
||||
# Server Configuration
|
||||
HOST=0.0.0.0
|
||||
PORT=5000
|
||||
|
||||
# Security Configuration
|
||||
MAX_CONTENT_LENGTH=1024 * 1024 # 1MB max upload size
|
||||
WTF_CSRF_ENABLED=true
|
||||
|
||||
# Logging Configuration
|
||||
LOG_LEVEL=INFO
|
||||
LOG_FILE=/var/log/lms-c/app.log
|
||||
|
||||
# Database Configuration (if using one in future)
|
||||
# DATABASE_URL=postgresql://user:password@localhost/dbname
|
||||
|
||||
# External Services (if applicable)
|
||||
# SMTP_SERVER=smtp.example.com
|
||||
# SMTP_PORT=587
|
||||
# SMTP_USERNAME=user@example.com
|
||||
# SMTP_PASSWORD=password
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"TCP": {
|
||||
"443": {
|
||||
"HTTPS": true
|
||||
}
|
||||
},
|
||||
"Web": {
|
||||
"${TS_CERT_DOMAIN}:443": {
|
||||
"Handlers": {
|
||||
"/": {
|
||||
"Proxy": "http://elemes:5000"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"AllowFunnel": {
|
||||
"${TS_CERT_DOMAIN}:443": true
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
# Gunicorn configuration file for production
|
||||
|
||||
# Server socket
|
||||
bind = "0.0.0.0:5000"
|
||||
backlog = 2048
|
||||
|
||||
# Worker processes
|
||||
workers = 4
|
||||
worker_class = "sync"
|
||||
worker_connections = 1000
|
||||
timeout = 120
|
||||
keepalive = 5
|
||||
max_requests = 1000
|
||||
max_requests_jitter = 100
|
||||
preload_app = True
|
||||
|
||||
# Security
|
||||
limit_request_line = 4094
|
||||
limit_request_fields = 100
|
||||
limit_request_field_size = 8190
|
||||
|
||||
# Logging
|
||||
accesslog = "-"
|
||||
errorlog = "-"
|
||||
loglevel = "info"
|
||||
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" %(D)s'
|
||||
|
||||
# Process naming
|
||||
proc_name = 'lms-c'
|
||||
|
||||
# Server mechanics
|
||||
user = 'app'
|
||||
group = 'app'
|
||||
tmp_upload_dir = None
|
||||
|
||||
# SSL (uncomment and configure if using SSL)
|
||||
# keyfile = '/path/to/keyfile'
|
||||
# certfile = '/path/to/certfile'
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
lms-c:
|
||||
elemes:
|
||||
build: .
|
||||
container_name: elemes
|
||||
ports:
|
||||
- "5000:5000"
|
||||
volumes:
|
||||
|
|
@ -10,6 +11,28 @@ services:
|
|||
- ./static:/app/static
|
||||
- ./templates:/app/templates
|
||||
- ../tokens_siswa.csv:/app/tokens.csv
|
||||
env_file:
|
||||
- ../.env
|
||||
command: gunicorn --config gunicorn.conf.py app:app
|
||||
elemes-ts:
|
||||
image: docker.io/tailscale/tailscale:latest
|
||||
container_name: elemes-ts
|
||||
hostname: ${ELEMES_HOST}
|
||||
environment:
|
||||
- FLASK_ENV=development
|
||||
command: python app.py
|
||||
- TS_AUTHKEY=${TS_AUTHKEY}
|
||||
- TS_SERVE_CONFIG=/config/sinau-c-tail.json
|
||||
- TS_STATE_DIR=/var/lib/tailscale
|
||||
- TS_USERSPACE=true
|
||||
volumes:
|
||||
- ./state:/var/lib/tailscale
|
||||
- ../config:/config
|
||||
- /dev/net/tun:/dev/net/tun
|
||||
cap_add:
|
||||
- net_admin
|
||||
- sys_module
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
main_network:
|
||||
drive: bridge
|
||||
network_mode: service:elemes-ts
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
Flask==2.3.3
|
||||
markdown==3.5
|
||||
gunicorn==21.2.0
|
||||
flask-talisman==1.1.0
|
||||
18
start.sh
18
start.sh
|
|
@ -5,19 +5,19 @@
|
|||
echo "Starting C Programming Learning Management System..."
|
||||
|
||||
# Check if container is already running
|
||||
if [ "$(podman ps -q -f name=lms-c-container)" ]; then
|
||||
echo "Container is already running. Access the application at http://localhost:5000"
|
||||
exit 0
|
||||
if [ "$(podman ps -q -f name=elemes-container)" ]; then
|
||||
echo "Container is already running. Access the application at http://localhost:5000"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if container exists but is stopped
|
||||
if [ "$(podman ps -aq -f name=lms-c-container)" ]; then
|
||||
echo "Starting existing container..."
|
||||
podman start lms-c-container
|
||||
if [ "$(podman ps -aq -f name=elemes-container)" ]; then
|
||||
echo "Starting existing container..."
|
||||
podman start elemes-container
|
||||
else
|
||||
# Build and run the container
|
||||
echo "Building and starting container..."
|
||||
podman-compose up --build -d
|
||||
# Build and run the container
|
||||
echo "Building and starting container..."
|
||||
podman-compose up --build -d
|
||||
fi
|
||||
|
||||
echo "Application is now running. Access at http://localhost:5000"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Test script for LMS-C Production Environment
|
||||
|
||||
echo "Starting LMS-C Production Environment Tests..."
|
||||
|
||||
# Start the application
|
||||
echo "Starting the application..."
|
||||
cd ..
|
||||
./start.sh
|
||||
cd test
|
||||
|
||||
# Wait for the application to start
|
||||
echo "Waiting for application to start..."
|
||||
sleep 10
|
||||
|
||||
# Test 1: Check if the home page loads and displays lessons
|
||||
echo "Test 1: Checking home page and lesson display..."
|
||||
HOME_PAGE_CHECK=$(curl -s http://localhost:5000/ | grep -i "Available Lessons" | wc -l)
|
||||
if [ $HOME_PAGE_CHECK -gt 0 ]; then
|
||||
echo "✓ Test 1 PASSED: Home page displays lessons correctly"
|
||||
else
|
||||
echo "✗ Test 1 FAILED: Home page does not display lessons"
|
||||
fi
|
||||
|
||||
# Test 2: Check if specific lesson pages load
|
||||
echo "Test 2: Checking lesson page loading..."
|
||||
LESSON_PAGE_CHECK=$(curl -s http://localhost:5000/lesson/welcome.md | grep -i "C Programming Learning System" | wc -l)
|
||||
if [ $LESSON_PAGE_CHECK -gt 0 ]; then
|
||||
echo "✓ Test 2 PASSED: Lesson pages load correctly"
|
||||
else
|
||||
echo "✗ Test 2 FAILED: Lesson pages do not load"
|
||||
fi
|
||||
|
||||
# Test 3: Test the code compilation API
|
||||
echo "Test 3: Testing code compilation API..."
|
||||
COMPILATION_TEST=$(curl -s -X POST http://localhost:5000/compile \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"code":"#include <stdio.h>\n\nint main() {\n printf(\"Hello, World!\\n\");\n return 0;\n}"}')
|
||||
|
||||
# Check if the response contains success: true and the expected output
|
||||
if echo "$COMPILATION_TEST" | grep -q '"success":true' && echo "$COMPILATION_TEST" | grep -q "Hello, World!"; then
|
||||
echo "✓ Test 3 PASSED: Code compilation API works correctly"
|
||||
else
|
||||
echo "✗ Test 3 FAILED: Code compilation API not working"
|
||||
echo " Response: $COMPILATION_TEST"
|
||||
fi
|
||||
|
||||
# Test 4: Test with a more complex C program
|
||||
echo "Test 4: Testing complex code compilation..."
|
||||
COMPLEX_CODE='{
|
||||
"code": "#include <stdio.h>\nint main() {\n int i, sum = 0;\n for (i = 1; i <= 5; i++) {\n sum += i;\n }\n printf(\"Sum of 1 to 5 is: %d\\n\", sum);\n return 0;\n}"
|
||||
}'
|
||||
|
||||
COMPLEX_TEST=$(curl -s -X POST http://localhost:5000/compile \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$COMPLEX_CODE")
|
||||
|
||||
if echo "$COMPLEX_TEST" | grep -q '"success":true' && echo "$COMPLEX_TEST" | grep -q "Sum of 1 to 5"; then
|
||||
echo "✓ Test 4 PASSED: Complex code compilation works correctly"
|
||||
else
|
||||
echo "✗ Test 4 FAILED: Complex code compilation not working"
|
||||
echo " Response: $COMPLEX_TEST"
|
||||
fi
|
||||
|
||||
# Test 5: Check if all expected lesson files are accessible
|
||||
echo "Test 5: Checking lesson accessibility..."
|
||||
LESSON_FILES=("welcome.md" "hello_world.md" "introduction_to_c.md" "arrays.md")
|
||||
ALL_LESSONS_ACCESSIBLE=true
|
||||
|
||||
for lesson in "${LESSON_FILES[@]}"; do
|
||||
lesson_check=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:5000/lesson/$lesson")
|
||||
if [ "$lesson_check" -ne 200 ]; then
|
||||
echo "✗ Lesson $lesson returned HTTP $lesson_check"
|
||||
ALL_LESSONS_ACCESSIBLE=false
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$ALL_LESSONS_ACCESSIBLE" = true ]; then
|
||||
echo "✓ Test 5 PASSED: All test lessons are accessible"
|
||||
else
|
||||
echo "✗ Test 5 FAILED: Some lessons are not accessible"
|
||||
fi
|
||||
|
||||
# Test 6: Check for errors in container logs
|
||||
echo "Test 6: Checking container logs for errors..."
|
||||
LOG_ERRORS=$(podman logs elemes_lms-c_1 2>&1 | grep -i error | wc -l)
|
||||
if [ $LOG_ERRORS -eq 0 ]; then
|
||||
echo "✓ Test 6 PASSED: No errors found in container logs"
|
||||
else
|
||||
echo "✗ Test 6 FAILED: Errors found in container logs"
|
||||
podman logs elemes_lms-c_1 | grep -i error
|
||||
fi
|
||||
|
||||
# Stop the application
|
||||
echo "Stopping the application..."
|
||||
cd ..
|
||||
./stop.sh
|
||||
cd test
|
||||
|
||||
echo "All tests completed!"
|
||||
Loading…
Reference in New Issue