Add WebApp KubeDiagrams

This commit is contained in:
Sadallah
2026-02-10 10:51:54 +01:00
parent b404f34f6f
commit 75146122a0
5761 changed files with 502699 additions and 0 deletions

332
webapp/README.md Normal file
View File

@@ -0,0 +1,332 @@
## Project Structure
Web Interface for generating Kubernetes diagrams from manifests, Helm charts, or Helmfile files using Kubediagrams.
# KubeDiagrams Web App
A modern web interface for generating Kubernetes architecture diagrams from manifests, Helm charts, or Helmfile configurations using [KubeDiagrams](https://github.com/philippemerle/KubeDiagrams).
## ✨ Features
- **Multiple Input Types**: Support for Kubernetes manifests, Helm charts, and Helmfile configurations
- **Flexible Output Formats**: Generate diagrams in PNG, SVG, PDF, DOT, and interactive HTML
- **Interactive Viewer**: Explore diagrams with an interactive web viewer
- **Built-in Examples**: Pre-loaded examples for quick testing
- **History Management**: Keep track of your diagram generations
- **Docker Support**: Easy deployment with Docker and Docker Compose
- **Access Logging**: Apache Combined Log format compatible with GoAccess
---
## Quick Start
### Using Docker Compose (Recommended)
1. **Clone the repository**
```bash
git clone <repository-url>
cd kubediagramswebui
```
2. **Start the application**
```bash
docker-compose up -d
```
3. **Access the application**
- Open your browser and navigate to `http://localhost:8080`
That's it! The application is now running with both frontend and backend services.
### Stopping the application
```bash
docker-compose down
```
---
## Prerequisites
### Server-Side Tools (Required) (Include in requirements.txt)
The following command-line tools must be installed and available in your PATH:
- **`kube-diagrams/helm-diagrams`** - For generating diagrams from Kubernetes manifests and for generating diagrams from Helm charts ([Installation](https://github.com/philippemerle/KubeDiagrams))
- **`helmfile`** - Required only for Helmfile tab functionality ([Installation](https://github.com/helmfile/helmfile))
### Docker Deployment
- Docker Engine 20.10+
- Docker Compose
### Manual Deployment
- **Backend**: Python 3.8+, pip, venv
- **Frontend**: Node.js 18+, npm
---
## Project Structure
```
webapp/
├── backend/ # Python/Flask backend
│ ├── routes/ # Flask route handlers
│ │ ├── manifest.py # Manifest diagram generation endpoints
│ │ ├── helm.py # Helm chart diagram endpoints
│ │ ├── helmfile.py # Helmfile diagram endpoints
│ │ └── submit.py # Feedback submission endpoint
│ ├── services/ # Business logic layer
│ │ ├── manifestService.py # Manifest processing service
│ │ ├── helmService.py # Helm processing service
│ │ ├── helmfileService.py # Helmfile processing service
│ │ ├── file_manager.py # File operations manager
│ │ └── models.py # Data models
│ ├── utils/ # Utility modules
│ │ ├── access_logger.py # Request logging
│ │ ├── logger.py # General logging
│ │ ├── response_builder.py # API response builder
│ │ └── validators.py # Input validation
│ ├── app.py # Flask application entry point
│ ├── config.py # Configuration settings
│ ├── constants.py # Global constants
│ ├── requirements.txt # Python dependencies
│ ├── Dockerfile # Backend Docker image
│ └── logs/ # Log files (auto-rotation)
├── frontend/ # React/Vite frontend
│ ├── src/
│ │ ├── components/ # React components
│ │ │ ├── common/ # Reusable UI components
│ │ │ ├── options/ # Diagram configuration components
│ │ │ └── tabs/ # Main tab components
│ │ │ ├── ManifestTab/ # Kubernetes manifest tab
│ │ │ ├── HelmTab/ # Helm chart tab
│ │ │ ├── HelmFileTab/ # Helmfile tab
│ │ │ └── InteractiveViewerTab/ # Interactive viewer
│ │ ├── examples/ # Example registry
│ │ ├── hooks/ # Custom React hooks
│ │ ├── services/ # API client services
│ │ ├── utils/ # Utility functions
│ │ ├── App.jsx # Main application component
│ │ └── main.jsx # Application entry point
│ ├── public/
│ │ ├── examples/ # Example YAML files
│ │ │ ├── manifests/ # Manifest examples
│ │ │ └── helmfiles/ # Helmfile examples
│ │ └── interactive_viewer/ # Interactive viewer assets
│ ├── package.json # NPM dependencies
│ ├── vite.config.js # Vite configuration
│ ├── apache.conf # Apache reverse proxy config
│ └── Dockerfile # Frontend Docker image
└── docker-compose.yml # Docker Compose orchestration
```
---
## Manual Installation (Without Docker)
### Backend Setup
1. **Navigate to backend directory**
```bash
cd backend
```
2. **Create and activate virtual environment**
```bash
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
```
3. **Install dependencies**
```bash
pip install -r requirements.txt
```
4. **Start the Flask server**
```bash
python3 app.py
```
The backend server will be available at `http://localhost:5000`
### Frontend Setup
1. **Navigate to frontend directory**
```bash
cd frontend
```
2. **Install dependencies**
```bash
npm install
```
or
```bash
npm ci
```
3. **Start the development server**
```bash
npm run dev
```
The frontend will be available at `http://localhost:5173`
---
## Docker Deployment
### Architecture
The Docker Compose setup consists of two services:
- **Frontend**: Apache2 server serving React static files and acting as reverse proxy to the backend
- **Backend**: Python/Flask application with Gunicorn WSGI server running KubeDiagrams
### Configuration
#### Environment Variables
**Backend** (`backend/Dockerfile` or `docker-compose.yml`):
- `FLASK_ENV`: Set to `production` for production deployment
- `BEHIND_PROXY`: Set to `true` when running behind a reverse proxy (default: `true`)
- `PROXY_X_FOR`: Number of trusted proxies (default: `1`)
**Frontend** (`docker-compose.yml`):
- `BACKEND_URL`: Backend service URL (default: `http://backend:5000`)
#### Ports
- **Frontend**: Port `8080` (mapped to container port `80`)
- **Backend**: Port `5000` (internal only, accessed via frontend proxy)
### Building and Running
**Build and start services**:
```bash
docker-compose up --build
```
**Start in detached mode**:
```bash
docker-compose up -d
```
**View logs**:
```bash
docker-compose logs -f
```
**Stop services**:
```bash
docker-compose down
```
### Health Checks
The backend includes a health check endpoint at `/api/health` that Docker uses to monitor service health.
---
## Logging
The Flask backend generates detailed access logs in **Apache Combined Log format**, compatible with tools like **GoAccess** for analysis.
### Log Location
- **Docker**: `./backend/logs/access.log` (persisted via volume mount)
- **Manual**: `backend/logs/access.log`
### Log Format
```
IP - - [datetime] "METHOD PATH PROTOCOL" STATUS SIZE "REFERER" "USER-AGENT" TIME_MS
```
### Log Rotation
- **Frequency**: Daily at midnight
- **Retention**: 30 days
- **Format**: `access.log.YYYY-MM-DD`
### IP Address Detection
When running behind a reverse proxy (Apache, Nginx), the backend correctly identifies client IPs using `X-Forwarded-For` headers.
**Debug endpoint**: `GET /api/debug/ip` - Returns IP detection information
---
## Usage Guide
### 1. Kubernetes Manifest Tab
Generate diagrams from raw Kubernetes YAML manifests.
**Steps**:
1. Select the "Manifest" tab
2. Paste your Kubernetes YAML or load an example
3. Configure diagram options (format, orientation, colors, etc.)
4. Click "Generate Diagram"
5. Download the generated diagram or view it interactively
**Supported Resources**: Deployments, StatefulSets, Services, Ingresses, ConfigMaps, Secrets, PVCs, and more.
### 2. Helm Chart Tab
Generate diagrams from Helm chart URLs.
**Steps**:
1. Select the "Helm" tab
2. Enter the Helm chart URL (e.g., `https://charts.bitnami.com/bitnami/wordpress`)
3. Optionally provide a values file
4. Configure diagram options
5. Click "Generate Diagram"
**Note**: Supports both public Helm repositories and OCI registries.
### 3. Helmfile Tab
Generate diagrams from Helmfile configurations.
**Steps**:
1. Select the "Helmfile" tab
2. Paste your Helmfile YAML or load an example
3. Configure diagram options
4. Click "Generate Diagram"
**Requirement**: `helmfile` must be installed on the server.
### 4. Interactive Viewer
View diagrams in an interactive HTML viewer with zoom, pan, and search capabilities.
**Features**:
- Search nodes by name
- Highlight nodes on hover
- Pan and zoom controls
- Responsive design
---
## Configuration Options
### Diagram Options
- **Format**: PNG, SVG, PDF, DOT, Interactive HTML
- **CLI Arguments**: Optional custom parameters passed to the underlying KubeDiagrams tools
- **Without Namespace**: Option to generate diagrams without namespace grouping
- **Feedback System**: Rate diagrams (1-5 stars) and provide comments for improvement
### Available via CLI Arguments
The CLI arguments field allows you to pass additional parameters to customize diagram generation. Refer to [KubeDiagrams documentation](https://github.com/cloudogu/kubediagrams) for available options.
---
## Examples
The application includes built-in examples for quick testing:
### Manifest Examples
- **Redis StatefulSet**: Redis cluster with persistent storage
- **Microservices**: Multi-service application with ingress
- **WordPress**: WordPress with MySQL database
- **Cassandra**: Cassandra StatefulSet with headless service
### Helmfile Examples
- **Monitoring Stack**: Prometheus, Grafana, and AlertManager
### Adding Custom Examples
See `frontend/public/examples/README.md` for instructions on adding new examples.
---
## API Endpoints
### Backend API
- `POST /api/manifest/generate` - Generate diagram from manifest
- `POST /api/helm/generate` - Generate diagram from Helm chart
- `POST /api/helmfile/generate` - Generate diagram from Helmfile
- `POST /api/submit` - Submit feedback
---
## Troubleshooting
### Common Issues
**Issue**: "Command not found: kube-diagrams"
- **Solution**: Ensure KubeDiagrams is installed and in your PATH
**Issue**: Diagram generation fails with Helm charts
- **Solution**: Verify `helm-diagrams` is installed and the chart URL is accessible
**Issue**: Frontend cannot connect to backend
- **Solution**: Check that backend is running and CORS is properly configured
**Issue**: IP addresses showing as proxy IP instead of client IP
- **Solution**: Verify `BEHIND_PROXY=true` and `PROXY_X_FOR` is set correctly
### Debug Mode
Enable debug mode by setting `DEBUG=True` in `backend/config.py` for more detailed error messages.
---
## Testing
### Quick Test
1. Start both backend and frontend servers
2. Navigate to `http://localhost:8080` (Docker) or `http://localhost:5173` (manual)
3. Select the "Manifest" tab
4. Load an example (e.g., "Redis StatefulSet")
5. Click "Generate Diagram"
6. Verify the diagram is generated and can be downloaded
---
## Development
### Frontend Development
```bash
cd frontend
npm run dev # Start development server
npm run build # Build for production
npm run lint # Run ESLint
npm run format # Format code with Prettier
```
### Backend Development
```bash
cd backend
source venv/bin/activate
python3 app.py # Start Flask server in debug mode
```
### Technologies Used
**Backend**:
- Flask 3.1.2 - Web framework
- Gunicorn 23.0.0 - WSGI server
- KubeDiagrams 0.6.0 - Diagram generation
- PyYAML 6.0.2 - YAML parsing
**Frontend**:
- React 19.1.0 - UI framework
- Vite 6.3.5 - Build tool
- TailwindCSS 4.1.6 - Styling
- Lucide React - Icons
- Motion - Animations
---
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
---
## Support
For issues and questions, please open an issue on the GitHub repository.
---
## 🙏 Acknowledgments
- [Graphviz](https://graphviz.org/) - Graph visualization software

View File

@@ -0,0 +1,36 @@
# Virtual environment
venv/
.venv/
env/
# Python cache
__pycache__/
*.py[cod]
*$py.class
*.so
# Logs (will be mounted as volume)
logs/*.log
logs/*.csv
# Development files
.git
.gitignore
*.md
# IDE
.vscode/
.idea/
# Test files
test-*.png
test-*.svg
*.test.py
# OS files
.DS_Store
Thumbs.db
# Temporary files
*.tmp
*.bak

63
webapp/backend/Dockerfile Normal file
View File

@@ -0,0 +1,63 @@
# =============================================================================
# KubeDiagrams Backend - Dockerfile
# =============================================================================
# Base image from KubeDiagrams project (Philippe Merle)
# Includes: Helm, Graphviz, Python, PyYAML, diagrams
# =============================================================================
# --- Stage 1: Get Helm binary ---
FROM docker.io/alpine/helm:3 AS helm
# --- Stage 2: Build backend ---
FROM docker.io/python:3.13-alpine AS base
# Install system dependencies
RUN apk update && apk add --no-cache \
graphviz \
bash \
ttf-freefont \
curl \
&& rm -rf /var/cache/apk/*
# Copy Helm from first stage
COPY --from=helm /usr/bin/helm /usr/local/bin/helm
# Install Helmfile from GitHub releases (Alpine/musl version)
ARG HELMFILE_VERSION=1.2.3
RUN curl -fsSL -o /tmp/helmfile.tar.gz \
"https://github.com/helmfile/helmfile/releases/download/v${HELMFILE_VERSION}/helmfile_${HELMFILE_VERSION}_linux_386.tar.gz" && \
tar -xzf /tmp/helmfile.tar.gz -C /usr/local/bin helmfile && \
chmod +x /usr/local/bin/helmfile && \
rm /tmp/helmfile.tar.gz
# Set working directory
WORKDIR /app
# Copy requirements first (for Docker layer caching)
COPY requirements.txt .
# Install Python dependencies
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir -r requirements.txt
# Copy backend application code
COPY . .
# Create logs directory
RUN mkdir -p logs && chmod 755 logs
# Environment variables
ENV FLASK_APP=app.py
ENV FLASK_ENV=production
ENV PYTHONUNBUFFERED=1
ENV BEHIND_PROXY=true
ENV PROXY_X_FOR=1
# Expose port
EXPOSE 5000
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
CMD curl --fail --silent http://localhost:5000/api/health || exit 1
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "4", "--timeout", "120", "--access-logfile", "-", "--error-logfile", "-", "app:app"]

Binary file not shown.

Binary file not shown.

Binary file not shown.

112
webapp/backend/app.py Normal file
View File

@@ -0,0 +1,112 @@
"""Flask Application for KubeDiagrams Web UI."""
from flask import Flask, g, request, jsonify
from flask_cors import CORS
from werkzeug.middleware.proxy_fix import ProxyFix
from config import Config, setup_logging
from routes.manifest import manifest_bp
from routes.helm import helm_bp
from routes.helmfile import helmfile_bp
from routes.submit import submit_bp
from utils.access_logger import log_request, get_real_ip, get_all_ip_headers
from time import time
def create_app():
app = Flask(__name__)
# Health check endpoint
@app.route('/api/health', methods=['GET'])
def health_check():
"""Health check endpoint for monitoring and testing."""
return jsonify({
'status': 'healthy',
'service': 'kubediagrams-backend',
'version': '1.0.0'
}), 200
# Debug endpoint for IP testing
@app.route('/api/debug/ip', methods=['GET'])
def debug_ip():
"""
Debug endpoint to check IP detection.
Returns all IP-related information for debugging proxy configuration.
"""
return jsonify({
'detected_ip': get_real_ip(),
'remote_addr': request.remote_addr,
'headers': get_all_ip_headers(),
'behind_proxy': Config.BEHIND_PROXY,
'proxy_x_for': Config.PROXY_X_FOR
}), 200
# Proxy Configuration
# When running behind a reverse proxy (nginx, Apache, HAProxy), the proxy
# forwards requests to the application. By default, Flask sees the proxy's IP
# instead of the real client IP. ProxyFix corrects this by reading the
# X-Forwarded-* headers that the proxy sets.
if Config.BEHIND_PROXY:
app.wsgi_app = ProxyFix(
app.wsgi_app,
x_for=Config.PROXY_X_FOR, # Number of proxies setting X-Forwarded-For
x_proto=Config.PROXY_X_PROTO, # Number of proxies setting X-Forwarded-Proto
x_host=Config.PROXY_X_HOST, # Number of proxies setting X-Forwarded-Host
x_prefix=Config.PROXY_X_PREFIX # Number of proxies setting X-Forwarded-Prefix
)
# CORS Configuration
if Config.CORS_ENABLED:
CORS(app)
# Logging Configuration
setup_logging()
# Middleware pour logger les requêtes
@app.before_request
def before_request():
"""Save request start time for performance logging."""
g.request_start_time = time()
@app.after_request
def after_request(response):
"""Log request in Apache Combined Log Format."""
# Skip logging for health checks to avoid log spam
if request.path == '/api/health':
return response
# Get response size
response_size = response.calculate_content_length() or 0
# Log the request
log_request(
status_code=response.status_code,
response_size=response_size
)
return response
# Blueprints registration
app.register_blueprint(manifest_bp)
app.register_blueprint(helm_bp)
app.register_blueprint(helmfile_bp)
app.register_blueprint(submit_bp)
return app
app = create_app() # App Initialization
if __name__ == "__main__":
print("=" * 50)
print("Flask Application Configuration")
print("=" * 50)
print(f"BEHIND_PROXY: {Config.BEHIND_PROXY}")
print(f"PROXY_X_FOR: {Config.PROXY_X_FOR}")
print(f"PROXY_X_PROTO: {Config.PROXY_X_PROTO}")
print(f"PROXY_X_HOST: {Config.PROXY_X_HOST}")
print(f"PROXY_X_PREFIX: {Config.PROXY_X_PREFIX}")
print(f"DEBUG: {Config.DEBUG}")
print(f"PORT: {Config.PORT}")
print(f"HOST: {Config.HOST}")
print("=" * 50)
print("")
app.run(port=Config.PORT, debug=Config.DEBUG)

95
webapp/backend/config.py Normal file
View File

@@ -0,0 +1,95 @@
"""Configuration Flask application."""
import os
import logging
from logging.handlers import TimedRotatingFileHandler
from datetime import datetime, time as dt_time
class Config:
"""Config App and Logger."""
# Flask
DEBUG = True
PORT = 5000
HOST = 'localhost'
# CORS
CORS_ENABLED = True
# Proxy Configuration
# Set to True when running behind a reverse proxy (nginx, Apache, etc.)
# This enables proper forwarding of client IP addresses
BEHIND_PROXY = os.environ.get('BEHIND_PROXY', 'false').lower() == 'true'
# Number of trusted proxies in front of the application
# X-Forwarded-For: client, proxy1, proxy2 -> set to 2 if you have 2 proxies
PROXY_X_FOR = int(os.environ.get('PROXY_X_FOR', '1'))
PROXY_X_PROTO = int(os.environ.get('PROXY_X_PROTO', '1'))
PROXY_X_HOST = int(os.environ.get('PROXY_X_HOST', '1'))
PROXY_X_PREFIX = int(os.environ.get('PROXY_X_PREFIX', '1'))
LOG_DIR = "logs"
LOG_FILE = "access.log"
LOG_FORMAT = '%(message)s'
LOG_LEVEL = logging.INFO
LOG_ROTATION = "midnight"
LOG_INTERVAL = 1
LOG_BACKUP_COUNT = 30
LOG_ENCODING = 'utf-8'
LOG_SUFFIX = "%Y-%m-%d"
LOGGER_NAME = "access_logger"
# Disable automatic rotation based on file modification time
# This prevents creating files with old dates
LOG_USE_UTC = False
# Fichiers
FEEDBACK_FILE = "feedback.txt"
@classmethod
def get_log_path(cls):
"""Return path of the logFile."""
return os.path.join(cls.LOG_DIR, cls.LOG_FILE)
def setup_logging():
"""Config log system with proper rotation handling."""
# Create a logs directory if it doesn't exist
os.makedirs(Config.LOG_DIR, exist_ok=True)
# Create a formatter
log_formatter = logging.Formatter(Config.LOG_FORMAT)
log_path = Config.get_log_path()
# Create a handler with rotation
log_handler = TimedRotatingFileHandler(
log_path,
when=Config.LOG_ROTATION,
interval=Config.LOG_INTERVAL,
backupCount=Config.LOG_BACKUP_COUNT,
encoding=Config.LOG_ENCODING,
utc=Config.LOG_USE_UTC
)
log_handler.setFormatter(log_formatter)
log_handler.suffix = Config.LOG_SUFFIX
current_time = datetime.now()
# Calculate next midnight
next_midnight = datetime.combine(
current_time.date(),
dt_time(0, 0, 0)
)
if current_time >= next_midnight:
# If we're past midnight today, rollover at next midnight
from datetime import timedelta
next_midnight = next_midnight + timedelta(days=1)
# Set the rollover time (in seconds since epoch)
log_handler.rolloverAt = next_midnight.timestamp()
# Config logger
logger = logging.getLogger(Config.LOGGER_NAME)
logger.setLevel(Config.LOG_LEVEL)
# Remove existing handlers to avoid duplicates
logger.handlers.clear()
logger.addHandler(log_handler)
return logger

View File

@@ -0,0 +1,23 @@
"""Constantes of the backend"""
import re
# Different format of mime_types
MIME_TYPES = {
"png": "image/png",
"jpg": "image/jpeg",
"jpeg": "image/jpeg",
"gif": "image/gif",
"svg": "image/svg+xml",
"pdf": "application/pdf",
"dot": "text/vnd.graphviz",
"dot_json": "application/json"
}
# no binary format
TEXT_FORMATS = {"svg", "dot", "dot_json"}
# Manifest_detector
MANIFEST_RE = re.compile(r'^\s*apiVersion\s*:\s*.+$', re.MULTILINE)
KIND_RE = re.compile(r'^\s*kind\s*:\s*.+$', re.MULTILINE)
# Max log length
MAX_LOG_LENGTH = 999999
# file extensions
YAML_EXTENSIONS = ['.yaml', '.yml']
TGZ_EXTENSIONS = ['.tgz', '.tar.gz']

View File

@@ -0,0 +1,8 @@
[MANIFEST]
Note: 0
Commentaire: test
[HELMFILE]
Note: 5
Commentaire: ttt

View File

@@ -0,0 +1,24 @@
172.20.0.1 - - [27/Jan/2026:10:12:34 +0000] "POST /api/generate-diagram HTTP/1.1" 200 79665 "http://localhost:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 608.50ms
172.20.0.1 - - [27/Jan/2026:10:18:03 +0000] "POST /api/generate-diagram HTTP/1.1" 200 6554 "http://localhost:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 579.44ms
172.20.0.1 - - [27/Jan/2026:10:19:27 +0000] "GET /api/debug/ip HTTP/1.1" 200 278 "-" "curl/8.5.0" 0.74ms
192.168.1.59 - - [27/Jan/2026:10:20:59 +0000] "POST /api/generate-diagram HTTP/1.1" 200 91057 "http://192.168.1.123:8080/" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Mobile Safari/537.36" 476.36ms
192.168.1.123 - - [27/Jan/2026:10:21:23 +0000] "POST /api/generate-helmfile-diagram HTTP/1.1" 200 707287 "http://192.168.1.123:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 10285.02ms
10.201.9.161 - - [27/Jan/2026:12:18:52 +0000] "POST /api/generate-helm-diagram HTTP/1.1" 200 201474 "http://10.201.9.161:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 3347.54ms
10.201.8.211 - - [27/Jan/2026:12:22:49 +0000] "POST /api/generate-diagram HTTP/1.1" 200 79665 "http://10.201.9.161:8080/" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Mobile Safari/537.36" 451.44ms
172.20.0.1 - - [27/Jan/2026:12:24:03 +0000] "POST /api/generate-helmfile-diagram HTTP/1.1" 200 707287 "http://localhost:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 8655.16ms
10.201.9.161 - - [27/Jan/2026:12:24:09 +0000] "POST /api/generate-helm-diagram HTTP/1.1" 200 201474 "http://10.201.9.161:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 3420.22ms
10.201.8.211 - - [27/Jan/2026:12:24:59 +0000] "POST /api/generate-helm-diagram HTTP/1.1" 200 114224 "http://10.201.9.161:8080/" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Mobile Safari/537.36" 1229.77ms
10.201.9.161 - - [27/Jan/2026:12:25:01 +0000] "POST /api/generate-helm-diagram HTTP/1.1" 400 2469 "http://10.201.9.161:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 2978.06ms
172.20.0.1 - - [27/Jan/2026:12:25:15 +0000] "POST /api/generate-helm-diagram HTTP/1.1" 200 154735 "http://localhost:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 13762.43ms
172.20.0.1 - - [27/Jan/2026:12:51:51 +0000] "POST /api/generate-diagram HTTP/1.1" 200 6413 "http://localhost:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 490.70ms
172.20.0.1 - - [27/Jan/2026:12:52:42 +0000] "POST /api/generate-diagram HTTP/1.1" 200 79665 "http://localhost:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 519.98ms
172.20.0.1 - - [27/Jan/2026:12:53:53 +0000] "POST /api/generate-helmfile-diagram HTTP/1.1" 200 707287 "http://localhost:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 8321.61ms
10.201.9.161 - - [27/Jan/2026:13:22:17 +0000] "POST /api/generate-diagram HTTP/1.1" 200 79665 "http://10.201.9.161:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 561.96ms
10.201.9.161 - - [27/Jan/2026:13:24:12 +0000] "POST /api/generate-helmfile-diagram HTTP/1.1" 200 707287 "http://10.201.9.161:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 8609.22ms
10.201.8.211 - - [27/Jan/2026:13:42:54 +0000] "POST /api/generate-diagram HTTP/1.1" 200 79665 "http://10.201.9.161:8080/" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Mobile Safari/537.36" 452.02ms
10.201.9.161 - - [27/Jan/2026:13:50:05 +0000] "POST /api/generate-diagram HTTP/1.1" 200 93003 "http://10.201.9.161:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 646.66ms
10.201.9.161 - - [27/Jan/2026:13:51:25 +0000] "POST /api/generate-helm-diagram HTTP/1.1" 200 2797664 "http://10.201.9.161:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 15009.67ms
10.201.9.161 - - [27/Jan/2026:14:28:46 +0000] "POST /api/generate-diagram HTTP/1.1" 200 92580 "http://10.201.9.161:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 619.55ms
10.201.9.161 - - [27/Jan/2026:14:29:00 +0000] "POST /api/generate-diagram HTTP/1.1" 200 92580 "http://10.201.9.161:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 614.89ms
10.201.9.161 - - [27/Jan/2026:14:29:22 +0000] "POST /api/generate-diagram HTTP/1.1" 200 83194 "http://10.201.9.161:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 536.01ms
10.201.9.161 - - [27/Jan/2026:14:29:36 +0000] "POST /api/generate-diagram HTTP/1.1" 400 1269 "http://10.201.9.161:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" 521.76ms

View File

@@ -0,0 +1,121 @@
2025-11-28 10:46:59,647 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 10:47:17,174 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=png;chartUrl=oci://ghcr.io/argoproj/argo-helm/argo-cd;extraArgs=
2025-11-28 10:47:37,037 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=png;helmfile=;extraArgs=;withoutNamespace=False
2025-11-28 10:48:04,593 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n name: wordpress-mysql\n labels:\n app: wordpress\nspec:\n ports:\n - port: 3306\n selector:\n app: wordpress\n tier: mysql\n clusterIP: None\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: mysql-pv-claim\n labels:\n app: wordpress\nspec:\n accessModes:\n - ReadWriteOnce\n resources:\n requests:\n storage: 512M # instead of 20Gi\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wordpress-mysql\n labels:\n app: wordpress\nspec:\n selector:\n matchLabels:\n app: wordpress\n tier: mysql\n strategy:\n type: Recreate\n template:\n metadata:\n labels:\n app: wordpress\n tier: mysql\n spec:\n containers:\n - image: mysql:8.0\n name: mysql\n env:\n - name: MYSQL_ROOT_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n - name: MYSQL_DATABASE\n value: wordpress\n - name: MYSQL_USER\n value: wordpress\n - name: MYSQL_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n ports:\n - containerPort: 3306\n name: mysql\n volumeMounts:\n - name: mysql-persistent-storage\n mountPath: /var/lib/mysql\n volumes:\n - name: mysql-persistent-storage\n persistentVolumeClaim:\n claimName: mysql-pv-claim\n---\napiVersion: v1\nkind: Secret\nmetadata:\n name: mysql-pass\n labels:\n app: wordpress\ntype: Opaque\ndata:\n password: WU9VUl9QQVNTV09SRA==\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: wordpress\n labels:\n app: wordpress\nspec:\n ports:\n - port: 80\n selector:\n app: wordpress\n tier: frontend\n type: LoadBalancer\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: wp-pv-claim\n labels:\n app: wordpress\nspec:\n accessModes:\n - ReadWriteOnce\n resources:\n requests:\n storage: 512M # instead of 20Gi\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wordpress\n labels:\n app: wordpress\nspec:\n selector:\n matchLabels:\n app: wordpress\n tier: frontend\n strategy:\n type: Recreate\n template:\n metadata:\n labels:\n app: wordpress\n tier: frontend\n spec:\n containers:\n - image: wordpress:6.2.1-apache\n name: wordpress\n env:\n - name: WORDPRESS_DB_HOST\n value: wordpress-mysql\n - name: WORDPRESS_DB_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n - name: WORDPRESS_DB_USER\n value: wordpress\n ports:\n - containerPort: 80\n name: wordpress\n volumeMounts:\n - name: wordpress-persistent-storage\n mountPath: /var/www/html\n volumes:\n - name: wordpress-persistent-storage\n persistentVolumeClaim:\n claimName: wp-pv-claim\n
2025-11-28 10:48:07,055 ; 127.0.0.1 ; /api/generate-diagram ; format=jpg;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n name: wordpress-mysql\n labels:\n app: wordpress\nspec:\n ports:\n - port: 3306\n selector:\n app: wordpress\n tier: mysql\n clusterIP: None\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: mysql-pv-claim\n labels:\n app: wordpress\nspec:\n accessModes:\n - ReadWriteOnce\n resources:\n requests:\n storage: 512M # instead of 20Gi\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wordpress-mysql\n labels:\n app: wordpress\nspec:\n selector:\n matchLabels:\n app: wordpress\n tier: mysql\n strategy:\n type: Recreate\n template:\n metadata:\n labels:\n app: wordpress\n tier: mysql\n spec:\n containers:\n - image: mysql:8.0\n name: mysql\n env:\n - name: MYSQL_ROOT_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n - name: MYSQL_DATABASE\n value: wordpress\n - name: MYSQL_USER\n value: wordpress\n - name: MYSQL_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n ports:\n - containerPort: 3306\n name: mysql\n volumeMounts:\n - name: mysql-persistent-storage\n mountPath: /var/lib/mysql\n volumes:\n - name: mysql-persistent-storage\n persistentVolumeClaim:\n claimName: mysql-pv-claim\n---\napiVersion: v1\nkind: Secret\nmetadata:\n name: mysql-pass\n labels:\n app: wordpress\ntype: Opaque\ndata:\n password: WU9VUl9QQVNTV09SRA==\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: wordpress\n labels:\n app: wordpress\nspec:\n ports:\n - port: 80\n selector:\n app: wordpress\n tier: frontend\n type: LoadBalancer\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: wp-pv-claim\n labels:\n app: wordpress\nspec:\n accessModes:\n - ReadWriteOnce\n resources:\n requests:\n storage: 512M # instead of 20Gi\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wordpress\n labels:\n app: wordpress\nspec:\n selector:\n matchLabels:\n app: wordpress\n tier: frontend\n strategy:\n type: Recreate\n template:\n metadata:\n labels:\n app: wordpress\n tier: frontend\n spec:\n containers:\n - image: wordpress:6.2.1-apache\n name: wordpress\n env:\n - name: WORDPRESS_DB_HOST\n value: wordpress-mysql\n - name: WORDPRESS_DB_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n - name: WORDPRESS_DB_USER\n value: wordpress\n ports:\n - containerPort: 80\n name: wordpress\n volumeMounts:\n - name: wordpress-persistent-storage\n mountPath: /var/www/html\n volumes:\n - name: wordpress-persistent-storage\n persistentVolumeClaim:\n claimName: wp-pv-claim\n
2025-11-28 10:48:08,985 ; 127.0.0.1 ; /api/generate-diagram ; format=jpeg;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n name: wordpress-mysql\n labels:\n app: wordpress\nspec:\n ports:\n - port: 3306\n selector:\n app: wordpress\n tier: mysql\n clusterIP: None\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: mysql-pv-claim\n labels:\n app: wordpress\nspec:\n accessModes:\n - ReadWriteOnce\n resources:\n requests:\n storage: 512M # instead of 20Gi\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wordpress-mysql\n labels:\n app: wordpress\nspec:\n selector:\n matchLabels:\n app: wordpress\n tier: mysql\n strategy:\n type: Recreate\n template:\n metadata:\n labels:\n app: wordpress\n tier: mysql\n spec:\n containers:\n - image: mysql:8.0\n name: mysql\n env:\n - name: MYSQL_ROOT_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n - name: MYSQL_DATABASE\n value: wordpress\n - name: MYSQL_USER\n value: wordpress\n - name: MYSQL_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n ports:\n - containerPort: 3306\n name: mysql\n volumeMounts:\n - name: mysql-persistent-storage\n mountPath: /var/lib/mysql\n volumes:\n - name: mysql-persistent-storage\n persistentVolumeClaim:\n claimName: mysql-pv-claim\n---\napiVersion: v1\nkind: Secret\nmetadata:\n name: mysql-pass\n labels:\n app: wordpress\ntype: Opaque\ndata:\n password: WU9VUl9QQVNTV09SRA==\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: wordpress\n labels:\n app: wordpress\nspec:\n ports:\n - port: 80\n selector:\n app: wordpress\n tier: frontend\n type: LoadBalancer\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: wp-pv-claim\n labels:\n app: wordpress\nspec:\n accessModes:\n - ReadWriteOnce\n resources:\n requests:\n storage: 512M # instead of 20Gi\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wordpress\n labels:\n app: wordpress\nspec:\n selector:\n matchLabels:\n app: wordpress\n tier: frontend\n strategy:\n type: Recreate\n template:\n metadata:\n labels:\n app: wordpress\n tier: frontend\n spec:\n containers:\n - image: wordpress:6.2.1-apache\n name: wordpress\n env:\n - name: WORDPRESS_DB_HOST\n value: wordpress-mysql\n - name: WORDPRESS_DB_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n - name: WORDPRESS_DB_USER\n value: wordpress\n ports:\n - containerPort: 80\n name: wordpress\n volumeMounts:\n - name: wordpress-persistent-storage\n mountPath: /var/www/html\n volumes:\n - name: wordpress-persistent-storage\n persistentVolumeClaim:\n claimName: wp-pv-claim\n
2025-11-28 10:48:10,977 ; 127.0.0.1 ; /api/generate-diagram ; format=svg;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n name: wordpress-mysql\n labels:\n app: wordpress\nspec:\n ports:\n - port: 3306\n selector:\n app: wordpress\n tier: mysql\n clusterIP: None\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: mysql-pv-claim\n labels:\n app: wordpress\nspec:\n accessModes:\n - ReadWriteOnce\n resources:\n requests:\n storage: 512M # instead of 20Gi\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wordpress-mysql\n labels:\n app: wordpress\nspec:\n selector:\n matchLabels:\n app: wordpress\n tier: mysql\n strategy:\n type: Recreate\n template:\n metadata:\n labels:\n app: wordpress\n tier: mysql\n spec:\n containers:\n - image: mysql:8.0\n name: mysql\n env:\n - name: MYSQL_ROOT_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n - name: MYSQL_DATABASE\n value: wordpress\n - name: MYSQL_USER\n value: wordpress\n - name: MYSQL_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n ports:\n - containerPort: 3306\n name: mysql\n volumeMounts:\n - name: mysql-persistent-storage\n mountPath: /var/lib/mysql\n volumes:\n - name: mysql-persistent-storage\n persistentVolumeClaim:\n claimName: mysql-pv-claim\n---\napiVersion: v1\nkind: Secret\nmetadata:\n name: mysql-pass\n labels:\n app: wordpress\ntype: Opaque\ndata:\n password: WU9VUl9QQVNTV09SRA==\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: wordpress\n labels:\n app: wordpress\nspec:\n ports:\n - port: 80\n selector:\n app: wordpress\n tier: frontend\n type: LoadBalancer\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: wp-pv-claim\n labels:\n app: wordpress\nspec:\n accessModes:\n - ReadWriteOnce\n resources:\n requests:\n storage: 512M # instead of 20Gi\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wordpress\n labels:\n app: wordpress\nspec:\n selector:\n matchLabels:\n app: wordpress\n tier: frontend\n strategy:\n type: Recreate\n template:\n metadata:\n labels:\n app: wordpress\n tier: frontend\n spec:\n containers:\n - image: wordpress:6.2.1-apache\n name: wordpress\n env:\n - name: WORDPRESS_DB_HOST\n value: wordpress-mysql\n - name: WORDPRESS_DB_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n - name: WORDPRESS_DB_USER\n value: wordpress\n ports:\n - containerPort: 80\n name: wordpress\n volumeMounts:\n - name: wordpress-persistent-storage\n mountPath: /var/www/html\n volumes:\n - name: wordpress-persistent-storage\n persistentVolumeClaim:\n claimName: wp-pv-claim\n
2025-11-28 10:48:14,483 ; 127.0.0.1 ; /api/generate-diagram ; format=pdf;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n name: wordpress-mysql\n labels:\n app: wordpress\nspec:\n ports:\n - port: 3306\n selector:\n app: wordpress\n tier: mysql\n clusterIP: None\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: mysql-pv-claim\n labels:\n app: wordpress\nspec:\n accessModes:\n - ReadWriteOnce\n resources:\n requests:\n storage: 512M # instead of 20Gi\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wordpress-mysql\n labels:\n app: wordpress\nspec:\n selector:\n matchLabels:\n app: wordpress\n tier: mysql\n strategy:\n type: Recreate\n template:\n metadata:\n labels:\n app: wordpress\n tier: mysql\n spec:\n containers:\n - image: mysql:8.0\n name: mysql\n env:\n - name: MYSQL_ROOT_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n - name: MYSQL_DATABASE\n value: wordpress\n - name: MYSQL_USER\n value: wordpress\n - name: MYSQL_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n ports:\n - containerPort: 3306\n name: mysql\n volumeMounts:\n - name: mysql-persistent-storage\n mountPath: /var/lib/mysql\n volumes:\n - name: mysql-persistent-storage\n persistentVolumeClaim:\n claimName: mysql-pv-claim\n---\napiVersion: v1\nkind: Secret\nmetadata:\n name: mysql-pass\n labels:\n app: wordpress\ntype: Opaque\ndata:\n password: WU9VUl9QQVNTV09SRA==\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: wordpress\n labels:\n app: wordpress\nspec:\n ports:\n - port: 80\n selector:\n app: wordpress\n tier: frontend\n type: LoadBalancer\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: wp-pv-claim\n labels:\n app: wordpress\nspec:\n accessModes:\n - ReadWriteOnce\n resources:\n requests:\n storage: 512M # instead of 20Gi\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wordpress\n labels:\n app: wordpress\nspec:\n selector:\n matchLabels:\n app: wordpress\n tier: frontend\n strategy:\n type: Recreate\n template:\n metadata:\n labels:\n app: wordpress\n tier: frontend\n spec:\n containers:\n - image: wordpress:6.2.1-apache\n name: wordpress\n env:\n - name: WORDPRESS_DB_HOST\n value: wordpress-mysql\n - name: WORDPRESS_DB_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n - name: WORDPRESS_DB_USER\n value: wordpress\n ports:\n - containerPort: 80\n name: wordpress\n volumeMounts:\n - name: wordpress-persistent-storage\n mountPath: /var/www/html\n volumes:\n - name: wordpress-persistent-storage\n persistentVolumeClaim:\n claimName: wp-pv-claim\n
2025-11-28 10:48:18,374 ; 127.0.0.1 ; /api/generate-diagram ; format=dot;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n name: wordpress-mysql\n labels:\n app: wordpress\nspec:\n ports:\n - port: 3306\n selector:\n app: wordpress\n tier: mysql\n clusterIP: None\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: mysql-pv-claim\n labels:\n app: wordpress\nspec:\n accessModes:\n - ReadWriteOnce\n resources:\n requests:\n storage: 512M # instead of 20Gi\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wordpress-mysql\n labels:\n app: wordpress\nspec:\n selector:\n matchLabels:\n app: wordpress\n tier: mysql\n strategy:\n type: Recreate\n template:\n metadata:\n labels:\n app: wordpress\n tier: mysql\n spec:\n containers:\n - image: mysql:8.0\n name: mysql\n env:\n - name: MYSQL_ROOT_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n - name: MYSQL_DATABASE\n value: wordpress\n - name: MYSQL_USER\n value: wordpress\n - name: MYSQL_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n ports:\n - containerPort: 3306\n name: mysql\n volumeMounts:\n - name: mysql-persistent-storage\n mountPath: /var/lib/mysql\n volumes:\n - name: mysql-persistent-storage\n persistentVolumeClaim:\n claimName: mysql-pv-claim\n---\napiVersion: v1\nkind: Secret\nmetadata:\n name: mysql-pass\n labels:\n app: wordpress\ntype: Opaque\ndata:\n password: WU9VUl9QQVNTV09SRA==\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: wordpress\n labels:\n app: wordpress\nspec:\n ports:\n - port: 80\n selector:\n app: wordpress\n tier: frontend\n type: LoadBalancer\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: wp-pv-claim\n labels:\n app: wordpress\nspec:\n accessModes:\n - ReadWriteOnce\n resources:\n requests:\n storage: 512M # instead of 20Gi\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wordpress\n labels:\n app: wordpress\nspec:\n selector:\n matchLabels:\n app: wordpress\n tier: frontend\n strategy:\n type: Recreate\n template:\n metadata:\n labels:\n app: wordpress\n tier: frontend\n spec:\n containers:\n - image: wordpress:6.2.1-apache\n name: wordpress\n env:\n - name: WORDPRESS_DB_HOST\n value: wordpress-mysql\n - name: WORDPRESS_DB_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n - name: WORDPRESS_DB_USER\n value: wordpress\n ports:\n - containerPort: 80\n name: wordpress\n volumeMounts:\n - name: wordpress-persistent-storage\n mountPath: /var/www/html\n volumes:\n - name: wordpress-persistent-storage\n persistentVolumeClaim:\n claimName: wp-pv-claim\n
2025-11-28 10:48:25,333 ; 127.0.0.1 ; /api/generate-diagram ; format=dot_json;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n name: wordpress-mysql\n labels:\n app: wordpress\nspec:\n ports:\n - port: 3306\n selector:\n app: wordpress\n tier: mysql\n clusterIP: None\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: mysql-pv-claim\n labels:\n app: wordpress\nspec:\n accessModes:\n - ReadWriteOnce\n resources:\n requests:\n storage: 512M # instead of 20Gi\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wordpress-mysql\n labels:\n app: wordpress\nspec:\n selector:\n matchLabels:\n app: wordpress\n tier: mysql\n strategy:\n type: Recreate\n template:\n metadata:\n labels:\n app: wordpress\n tier: mysql\n spec:\n containers:\n - image: mysql:8.0\n name: mysql\n env:\n - name: MYSQL_ROOT_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n - name: MYSQL_DATABASE\n value: wordpress\n - name: MYSQL_USER\n value: wordpress\n - name: MYSQL_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n ports:\n - containerPort: 3306\n name: mysql\n volumeMounts:\n - name: mysql-persistent-storage\n mountPath: /var/lib/mysql\n volumes:\n - name: mysql-persistent-storage\n persistentVolumeClaim:\n claimName: mysql-pv-claim\n---\napiVersion: v1\nkind: Secret\nmetadata:\n name: mysql-pass\n labels:\n app: wordpress\ntype: Opaque\ndata:\n password: WU9VUl9QQVNTV09SRA==\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: wordpress\n labels:\n app: wordpress\nspec:\n ports:\n - port: 80\n selector:\n app: wordpress\n tier: frontend\n type: LoadBalancer\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: wp-pv-claim\n labels:\n app: wordpress\nspec:\n accessModes:\n - ReadWriteOnce\n resources:\n requests:\n storage: 512M # instead of 20Gi\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wordpress\n labels:\n app: wordpress\nspec:\n selector:\n matchLabels:\n app: wordpress\n tier: frontend\n strategy:\n type: Recreate\n template:\n metadata:\n labels:\n app: wordpress\n tier: frontend\n spec:\n containers:\n - image: wordpress:6.2.1-apache\n name: wordpress\n env:\n - name: WORDPRESS_DB_HOST\n value: wordpress-mysql\n - name: WORDPRESS_DB_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mysql-pass\n key: password\n - name: WORDPRESS_DB_USER\n value: wordpress\n ports:\n - containerPort: 80\n name: wordpress\n volumeMounts:\n - name: wordpress-persistent-storage\n mountPath: /var/www/html\n volumes:\n - name: wordpress-persistent-storage\n persistentVolumeClaim:\n claimName: wp-pv-claim\n
2025-11-28 10:49:16,214 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=png;helmfile=;extraArgs=;withoutNamespace=False
2025-11-28 10:50:49,741 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=png;helmfile=repositories:\n - name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n - name: grafana\n url: https://grafana.github.io/helm-charts\n\nreleases:\n - name: prometheus\n namespace: monitoring\n chart: prometheus-community/prometheus\n version: 15.0.0\n values:\n - server:\n persistentVolume:\n enabled: true\n size: 8Gi\n\n - name: grafana\n namespace: monitoring\n chart: grafana/grafana\n version: 6.50.0\n values:\n - adminPassword: changeme\n persistence:\n enabled: true\n size: 5Gi\n\n;extraArgs=;withoutNamespace=False
2025-11-28 10:51:45,236 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=dot_json;helmfile=repositories:\n - name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n - name: grafana\n url: https://grafana.github.io/helm-charts\n\nreleases:\n - name: prometheus\n namespace: monitoring\n chart: prometheus-community/prometheus\n version: 15.0.0\n values:\n - server:\n persistentVolume:\n enabled: true\n size: 8Gi\n\n - name: grafana\n namespace: monitoring\n chart: grafana/grafana\n version: 6.50.0\n values:\n - adminPassword: changeme\n persistence:\n enabled: true\n size: 5Gi\n\n;extraArgs=;withoutNamespace=False
2025-11-28 10:52:07,872 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=pdf;helmfile=repositories:\n - name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n - name: grafana\n url: https://grafana.github.io/helm-charts\n\nreleases:\n - name: prometheus\n namespace: monitoring\n chart: prometheus-community/prometheus\n version: 15.0.0\n values:\n - server:\n persistentVolume:\n enabled: true\n size: 8Gi\n\n - name: grafana\n namespace: monitoring\n chart: grafana/grafana\n version: 6.50.0\n values:\n - adminPassword: changeme\n persistence:\n enabled: true\n size: 5Gi\n\n;extraArgs=;withoutNamespace=False
2025-11-28 10:53:16,735 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=dot_json;helmfile=repositories:\n - name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n - name: grafana\n url: https://grafana.github.io/helm-charts\n\nreleases:\n - name: prometheus\n namespace: monitoring\n chart: prometheus-community/prometheus\n version: 15.0.0\n values:\n - server:\n persistentVolume:\n enabled: true\n size: 8Gi\n\n - name: grafana\n namespace: monitoring\n chart: grafana/grafana\n version: 6.50.0\n values:\n - adminPassword: changeme\n persistence:\n enabled: true\n size: 5Gi\n\n;extraArgs=;withoutNamespace=False
2025-11-28 10:55:33,948 ; 127.0.0.1 ; /api/generate-diagram ; format=dot_json;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 10:59:52,363 ; 127.0.0.1 ; /api/generate-diagram ; format=dot_json;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n name: redis-service\nspec:\n clusterIP: None\n selector:\n app: redis\n ports:\n - port: 6379\n targetPort: 6379\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: redis\nspec:\n serviceName: redis-service\n replicas: 3\n selector:\n matchLabels:\n app: redis\n template:\n metadata:\n labels:\n app: redis\n spec:\n containers:\n - name: redis\n image: redis:7.0\n ports:\n - containerPort: 6379\n volumeMounts:\n - name: data\n mountPath: /data\n volumeClaimTemplates:\n - metadata:\n name: data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n resources:\n requests:\n storage: 1Gi\n\n
2025-11-28 11:09:43,294 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command: \n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd\n
2025-11-28 11:09:58,166 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=png;helmfile=repositories:\n- name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n\nreleases:\n- name: prom-norbac-ubuntu\n namespace: prometheus\n chart: prometheus-community/prometheus\n set:\n - name: rbac.create\n value: false\n;extraArgs=;withoutNamespace=False
2025-11-28 11:21:48,531 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:21:54,810 ; 127.0.0.1 ; /api/generate-diagram ; format=jpg;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:21:57,647 ; 127.0.0.1 ; /api/generate-diagram ; format=jpeg;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:21:59,337 ; 127.0.0.1 ; /api/generate-diagram ; format=svg;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:22:03,383 ; 127.0.0.1 ; /api/generate-diagram ; format=pdf;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:22:11,671 ; 127.0.0.1 ; /api/generate-diagram ; format=dot;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:22:14,625 ; 127.0.0.1 ; /api/generate-diagram ; format=dot_json;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:22:25,918 ; 127.0.0.1 ; /api/generate-diagram ; format=svg;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:22:31,130 ; 127.0.0.1 ; /api/generate-diagram ; format=dot_json;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:22:51,772 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=png;chartUrl=https://charts.jetstack.io/cert-manager;extraArgs=
2025-11-28 11:22:55,039 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=jpg;chartUrl=https://charts.jetstack.io/cert-manager;extraArgs=
2025-11-28 11:22:57,897 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=jpeg;chartUrl=https://charts.jetstack.io/cert-manager;extraArgs=
2025-11-28 11:23:00,135 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=svg;chartUrl=https://charts.jetstack.io/cert-manager;extraArgs=
2025-11-28 11:23:02,246 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=pdf;chartUrl=https://charts.jetstack.io/cert-manager;extraArgs=
2025-11-28 11:23:05,591 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=dot;chartUrl=https://charts.jetstack.io/cert-manager;extraArgs=
2025-11-28 11:23:08,547 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=dot_json;chartUrl=https://charts.jetstack.io/cert-manager;extraArgs=
2025-11-28 11:23:33,878 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=png;helmfile=repositories:\n - name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n - name: grafana\n url: https://grafana.github.io/helm-charts\n\nreleases:\n - name: prometheus\n namespace: monitoring\n chart: prometheus-community/prometheus\n version: 15.0.0\n values:\n - server:\n persistentVolume:\n enabled: true\n size: 8Gi\n\n - name: grafana\n namespace: monitoring\n chart: grafana/grafana\n version: 6.50.0\n values:\n - adminPassword: changeme\n persistence:\n enabled: true\n size: 5Gi\n\n;extraArgs=;withoutNamespace=False
2025-11-28 11:23:38,138 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=dot_json;helmfile=repositories:\n - name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n - name: grafana\n url: https://grafana.github.io/helm-charts\n\nreleases:\n - name: prometheus\n namespace: monitoring\n chart: prometheus-community/prometheus\n version: 15.0.0\n values:\n - server:\n persistentVolume:\n enabled: true\n size: 8Gi\n\n - name: grafana\n namespace: monitoring\n chart: grafana/grafana\n version: 6.50.0\n values:\n - adminPassword: changeme\n persistence:\n enabled: true\n size: 5Gi\n\n;extraArgs=;withoutNamespace=False
2025-11-28 11:23:41,873 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=dot;helmfile=repositories:\n - name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n - name: grafana\n url: https://grafana.github.io/helm-charts\n\nreleases:\n - name: prometheus\n namespace: monitoring\n chart: prometheus-community/prometheus\n version: 15.0.0\n values:\n - server:\n persistentVolume:\n enabled: true\n size: 8Gi\n\n - name: grafana\n namespace: monitoring\n chart: grafana/grafana\n version: 6.50.0\n values:\n - adminPassword: changeme\n persistence:\n enabled: true\n size: 5Gi\n\n;extraArgs=;withoutNamespace=False
2025-11-28 11:23:45,957 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=pdf;helmfile=repositories:\n - name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n - name: grafana\n url: https://grafana.github.io/helm-charts\n\nreleases:\n - name: prometheus\n namespace: monitoring\n chart: prometheus-community/prometheus\n version: 15.0.0\n values:\n - server:\n persistentVolume:\n enabled: true\n size: 8Gi\n\n - name: grafana\n namespace: monitoring\n chart: grafana/grafana\n version: 6.50.0\n values:\n - adminPassword: changeme\n persistence:\n enabled: true\n size: 5Gi\n\n;extraArgs=;withoutNamespace=False
2025-11-28 11:23:49,736 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=svg;helmfile=repositories:\n - name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n - name: grafana\n url: https://grafana.github.io/helm-charts\n\nreleases:\n - name: prometheus\n namespace: monitoring\n chart: prometheus-community/prometheus\n version: 15.0.0\n values:\n - server:\n persistentVolume:\n enabled: true\n size: 8Gi\n\n - name: grafana\n namespace: monitoring\n chart: grafana/grafana\n version: 6.50.0\n values:\n - adminPassword: changeme\n persistence:\n enabled: true\n size: 5Gi\n\n;extraArgs=;withoutNamespace=False
2025-11-28 11:23:53,516 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=jpeg;helmfile=repositories:\n - name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n - name: grafana\n url: https://grafana.github.io/helm-charts\n\nreleases:\n - name: prometheus\n namespace: monitoring\n chart: prometheus-community/prometheus\n version: 15.0.0\n values:\n - server:\n persistentVolume:\n enabled: true\n size: 8Gi\n\n - name: grafana\n namespace: monitoring\n chart: grafana/grafana\n version: 6.50.0\n values:\n - adminPassword: changeme\n persistence:\n enabled: true\n size: 5Gi\n\n;extraArgs=;withoutNamespace=False
2025-11-28 11:23:58,608 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=jpg;helmfile=repositories:\n - name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n - name: grafana\n url: https://grafana.github.io/helm-charts\n\nreleases:\n - name: prometheus\n namespace: monitoring\n chart: prometheus-community/prometheus\n version: 15.0.0\n values:\n - server:\n persistentVolume:\n enabled: true\n size: 8Gi\n\n - name: grafana\n namespace: monitoring\n chart: grafana/grafana\n version: 6.50.0\n values:\n - adminPassword: changeme\n persistence:\n enabled: true\n size: 5Gi\n\n;extraArgs=;withoutNamespace=False
2025-11-28 11:33:17,932 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:33:28,865 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=True;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:33:39,735 ; 127.0.0.1 ; /api/generate-diagram ; format=svg;extraArgs=;withoutNamespace=True;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:33:51,170 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=png;chartUrl=https://charts.jetstack.io/cert-manager;extraArgs=
2025-11-28 11:34:15,179 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=svg;chartUrl=https://charts.jetstack.io/cert-manager;extraArgs=
2025-11-28 11:34:40,529 ; 127.0.0.1 ; /api/generate-diagram ; format=jpeg;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:37:44,041 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:37:48,813 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:37:51,380 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:37:52,775 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:38:03,632 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:38:45,637 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=png;chartUrl=https://grafana.github.io/helm-charts/grafana;extraArgs=
2025-11-28 11:40:55,865 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=png;chartUrl=https://grafana.github.io/helm-charts/grafana;extraArgs=
2025-11-28 11:41:04,816 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=svg;chartUrl=https://grafana.github.io/helm-charts/grafana;extraArgs=
2025-11-28 11:41:07,810 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=dot;chartUrl=https://grafana.github.io/helm-charts/grafana;extraArgs=
2025-11-28 11:41:10,493 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=dot_json;chartUrl=https://grafana.github.io/helm-charts/grafana;extraArgs=
2025-11-28 11:41:23,669 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:41:27,014 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=True;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:41:28,875 ; 127.0.0.1 ; /api/generate-diagram ; format=jpg;extraArgs=;withoutNamespace=True;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:41:31,995 ; 127.0.0.1 ; /api/generate-diagram ; format=svg;extraArgs=;withoutNamespace=True;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:41:34,858 ; 127.0.0.1 ; /api/generate-diagram ; format=pdf;extraArgs=;withoutNamespace=True;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 11:41:37,788 ; 127.0.0.1 ; /api/generate-diagram ; format=dot_json;extraArgs=;withoutNamespace=True;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 12:43:34,942 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 12:47:33,411 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 12:47:37,639 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=True;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 12:47:52,325 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=--without-namespace;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 12:48:02,889 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 12:48:05,278 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=True;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 12:54:15,841 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 12:54:17,956 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=True;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 12:54:20,984 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 12:57:21,847 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:05:52,802 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=png;chartUrl=https://kubernetes.github.io/ingress-nginx/ingress-nginx;extraArgs=
2025-11-28 13:17:41,041 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:17:46,245 ; 127.0.0.1 ; /api/generate-diagram ; format=jpg;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:17:48,736 ; 127.0.0.1 ; /api/generate-diagram ; format=jpeg;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:17:51,523 ; 127.0.0.1 ; /api/generate-diagram ; format=svg;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:17:53,849 ; 127.0.0.1 ; /api/generate-diagram ; format=pdf;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:17:56,179 ; 127.0.0.1 ; /api/generate-diagram ; format=dot;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:17:59,449 ; 127.0.0.1 ; /api/generate-diagram ; format=dot_json;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:18:42,089 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:21:19,948 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=png;chartUrl=https://prometheus-community.github.io/helm-charts/prometheus;extraArgs=
2025-11-28 13:21:25,710 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=dot_json;chartUrl=https://prometheus-community.github.io/helm-charts/prometheus;extraArgs=
2025-11-28 13:23:12,597 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:25:15,031 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:25:36,797 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=png;helmfile=repositories:\n- name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n\nreleases:\n- name: prom-norbac-ubuntu\n namespace: prometheus\n chart: prometheus-community/prometheus\n set:\n - name: rbac.create\n value: false\n;extraArgs=;withoutNamespace=False
2025-11-28 13:28:33,079 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:28:39,944 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=True;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:32:50,201 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:32:51,293 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:32:52,066 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:32:55,939 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:32:56,817 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:32:57,550 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:32:58,191 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:32:58,861 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:32:59,611 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:33:00,258 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:33:05,422 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=png;chartUrl=https://prometheus-community.github.io/helm-charts/prometheus;extraArgs=
2025-11-28 13:33:16,300 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=png;helmfile=repositories:\n - name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n - name: grafana\n url: https://grafana.github.io/helm-charts\n\nreleases:\n - name: prometheus\n namespace: monitoring\n chart: prometheus-community/prometheus\n version: 15.0.0\n values:\n - server:\n persistentVolume:\n enabled: true\n size: 8Gi\n\n - name: grafana\n namespace: monitoring\n chart: grafana/grafana\n version: 6.50.0\n values:\n - adminPassword: changeme\n persistence:\n enabled: true\n size: 5Gi\n\n;extraArgs=;withoutNamespace=False
2025-11-28 13:37:25,304 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:37:28,741 ; 127.0.0.1 ; /api/generate-diagram ; format=jpeg;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:37:31,008 ; 127.0.0.1 ; /api/generate-diagram ; format=svg;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:37:35,563 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=jpeg;helmfile=;extraArgs=;withoutNamespace=False
2025-11-28 13:37:36,927 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=jpeg;helmfile=;extraArgs=;withoutNamespace=False
2025-11-28 13:37:39,362 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=jpeg;helmfile=repositories:\n - name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n - name: grafana\n url: https://grafana.github.io/helm-charts\n\nreleases:\n - name: prometheus\n namespace: monitoring\n chart: prometheus-community/prometheus\n version: 15.0.0\n values:\n - server:\n persistentVolume:\n enabled: true\n size: 8Gi\n\n - name: grafana\n namespace: monitoring\n chart: grafana/grafana\n version: 6.50.0\n values:\n - adminPassword: changeme\n persistence:\n enabled: true\n size: 5Gi\n\n;extraArgs=;withoutNamespace=False
2025-11-28 13:38:17,604 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=jpeg;helmfile=repositories:\n - name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n - name: grafana\n url: https://grafana.github.io/helm-charts\n\nreleases:\n - name: prometheus\n namespace: monitoring\n chart: prometheus-community/prometheus\n version: 15.0.0\n values:\n - server:\n persistentVolume:\n enabled: true\n size: 8Gi\n\n - name: grafana\n namespace: monitoring\n chart: grafana/grafana\n version: 6.50.0\n values:\n - adminPassword: changeme\n persistence:\n enabled: true\n size: 5Gi\n\n;extraArgs=;withoutNamespace=False
2025-11-28 13:49:00,253 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 13:58:25,432 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 14:00:16,585 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=png;chartUrl=https://charts.bitnami.com/bitnami/redis;extraArgs=
2025-11-28 14:00:47,887 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 14:00:58,825 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=png;chartUrl=https://kubernetes.github.io/ingress-nginx/ingress-nginx;extraArgs=
2025-11-28 14:03:51,098 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=png;chartUrl=oci://ghcr.io/argoproj/argo-helm/argo-cd;extraArgs=
2025-11-28 14:04:06,132 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 16:40:40,648 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=png;chartUrl=http://charts.gitlab.io/gitlab;extraArgs=--set certmanager-issuer.email=someone@acme.com
2025-11-28 16:42:10,189 ; 127.0.0.1 ; /api/generate-helmfile-diagram ; format=png;helmfile=repositories:\n - name: prometheus-community\n url: https://prometheus-community.github.io/helm-charts\n - name: grafana\n url: https://grafana.github.io/helm-charts\n\nreleases:\n - name: prometheus\n namespace: monitoring\n chart: prometheus-community/prometheus\n version: 15.0.0\n values:\n - server:\n persistentVolume:\n enabled: true\n size: 8Gi\n\n - name: grafana\n namespace: monitoring\n chart: grafana/grafana\n version: 6.50.0\n values:\n - adminPassword: changeme\n persistence:\n enabled: true\n size: 5Gi\n\n;extraArgs=;withoutNamespace=False
2025-11-28 16:42:50,574 ; 127.0.0.1 ; /api/generate-helm-diagram ; format=png;chartUrl=https://kubernetes.github.io/dashboard/kubernetes-dashboard;extraArgs=
2025-11-28 16:43:07,083 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=False;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
2025-11-28 17:14:26,329 ; 127.0.0.1 ; /api/generate-diagram ; format=png;extraArgs=;withoutNamespace=True;manifest=apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: cassandra\n name: cassandra\nspec:\n clusterIP: None\n ports:\n - port: 9042\n selector:\n app: cassandra\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: cassandra\n labels:\n app: cassandra\nspec:\n serviceName: cassandra\n replicas: 3\n selector:\n matchLabels:\n app: cassandra\n template:\n metadata:\n labels:\n app: cassandra\n spec:\n terminationGracePeriodSeconds: 500\n containers:\n - name: cassandra\n image: gcr.io/google-samples/cassandra:v13\n imagePullPolicy: Always\n ports:\n - containerPort: 7000\n name: intra-node\n - containerPort: 7001\n name: tls-intra-node\n - containerPort: 7199\n name: jmx\n - containerPort: 9042\n name: cql\n resources:\n limits:\n cpu: "500m"\n memory: 1Gi\n requests:\n cpu: "500m"\n memory: 512M #CHANGED: instead of 1Gi\n securityContext:\n capabilities:\n add:\n - IPC_LOCK\n lifecycle:\n preStop:\n exec:\n command:\n - /bin/sh\n - -c\n - nodetool drain\n env:\n - name: MAX_HEAP_SIZE\n value: 512M\n - name: HEAP_NEWSIZE\n value: 100M\n - name: CASSANDRA_SEEDS\n value: "cassandra-0.cassandra.default.svc.cluster.local"\n - name: CASSANDRA_CLUSTER_NAME\n value: "K8Demo"\n - name: CASSANDRA_DC\n value: "DC1-K8Demo"\n - name: CASSANDRA_RACK\n value: "Rack1-K8Demo"\n - name: POD_IP\n valueFrom:\n fieldRef:\n fieldPath: status.podIP\n readinessProbe:\n exec:\n command:\n - /bin/bash\n - -c\n - echo OK #ERROR: if /ready-probe.sh\n initialDelaySeconds: 15\n timeoutSeconds: 5\n # These volume mounts are persistent. They are like inline claims,\n # but not exactly because the names need to match exactly one of\n # the stateful pod volumes.\n volumeMounts:\n - name: cassandra-data\n mountPath: /cassandra_data\n # These are converted to volume claims by the controller\n # and mounted at the paths mentioned above.\n # do not use these in production until ssd GCEPersistentDisk or other ssd pd\n volumeClaimTemplates:\n - metadata:\n name: cassandra-data\n spec:\n accessModes: [ "ReadWriteOnce" ]\n storageClassName: fast\n resources:\n requests:\n storage: 512M #CHANGED: instead of 1Gi\n---\nkind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: fast\nprovisioner: k8s.io/minikube-hostpath\nparameters:\n type: pd-ssd
Can't render this file because it contains an unexpected character in line 1 and column 1096.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
blinker==1.9.0
cfgv==3.4.0
click==8.2.1
diagrams==0.24.4
distlib==0.4.0
filelock==3.19.1
Flask==3.1.2
flask-cors==6.0.1
graphviz==0.20.3
gunicorn==23.0.0
identify==2.6.14
itsdangerous==2.2.0
Jinja2==3.1.6
KubeDiagrams==0.6.0
MarkupSafe==3.0.2
nodeenv==1.9.1
platformdirs==4.4.0
pre_commit==4.3.0
PyYAML==6.0.2
virtualenv==20.34.0
Werkzeug==3.1.3

View File

@@ -0,0 +1,7 @@
"""Routes Package Init File"""
from .manifest import manifest_bp
from .helm import helm_bp
from .helmfile import helmfile_bp
from .submit import submit_bp
__all__ = ['manifest_bp', 'helm_bp', 'helmfile_bp', 'submit_bp']

Binary file not shown.

View File

@@ -0,0 +1,49 @@
"""Routes for generating diagrams from Helm charts."""
from flask import Blueprint, request
from .utils import log_to_csv
from services import generate_from_helm
from utils import InputValidator, ResponseBuilder
helm_bp = Blueprint('helm', __name__)
@helm_bp.route('/api/generate-helm-diagram', methods=['POST'])
def generate_helm_diagram():
"""Generate a diagram from a Helm chart."""
data = request.get_json()
chart_url = data.get("chart", "")
output_format = (data.get("outputFormat") or "png").lower()
extra_args = data.get('extraArgs', '')
# Log to CSV only
client_ip = request.remote_addr
route = request.path
params = f"format={output_format};chartUrl={chart_url};extraArgs={extra_args}"
log_to_csv(client_ip, route, params)
# Chart URL validation
is_valid, error_msg = InputValidator.validate_helm_chart_url(chart_url)
if not is_valid:
return ResponseBuilder.validation_error("chart", error_msg)
# Output format validation
is_valid, error_msg = InputValidator.validate_output_format(output_format)
if not is_valid:
return ResponseBuilder.validation_error("outputFormat", error_msg)
# Extra arguments validation
is_valid, error_msg = InputValidator.validate_extra_args(extra_args)
if not is_valid:
return ResponseBuilder.validation_error("extraArgs", error_msg)
# Diagram generation through service
result = generate_from_helm(
chart_url=chart_url,
output_format=output_format,
extra_args=extra_args
)
# Returning the response
return ResponseBuilder.from_diagram_result(result)

View File

@@ -0,0 +1,57 @@
"""Route for diagram generation from Helmfiles."""
from flask import Blueprint, request
from routes.utils import log_to_csv
from services import generate_from_helmfile
from utils import InputValidator, ResponseBuilder
from .utils import compact_for_log
helmfile_bp = Blueprint('helmfile', __name__)
@helmfile_bp.route('/api/generate-helmfile-diagram', methods=['POST'])
def generate_helmfile_diagram():
"""Diagram generation from a Helmfile."""
data = request.get_json()
helmfile_content = data.get("content", "")
output_format = (data.get("outputFormat") or "png").lower()
extra_args = data.get("extraArgs", "").strip()
without_namespace = data.get("withoutNamespace", False)
# Log to CSV only
client_ip = request.remote_addr
route = request.path
params = f"format={output_format};helmfile={compact_for_log(helmfile_content)};extraArgs={compact_for_log(extra_args)};withoutNamespace={without_namespace}"
log_to_csv(client_ip, route, params)
# Helmfile validation
is_valid, error_msg = InputValidator.validate_helmfile(helmfile_content)
if not is_valid:
return ResponseBuilder.validation_error("content", error_msg)
# Verify it doesn't look like a Manifest
if InputValidator.looks_like_manifest(helmfile_content):
return ResponseBuilder.error(
"This looks like a Manifest. Please use the Manifest tab for this content."
)
# Output format validation
is_valid, error_msg = InputValidator.validate_output_format(output_format)
if not is_valid:
return ResponseBuilder.validation_error("outputFormat", error_msg)
# Extra arguments validation
is_valid, error_msg = InputValidator.validate_extra_args(extra_args)
if not is_valid:
return ResponseBuilder.validation_error("extraArgs", error_msg)
# Diagram generation through service
result = generate_from_helmfile(
helmfile_content=helmfile_content,
output_format=output_format,
extra_args=extra_args,
without_namespace=without_namespace
)
# Returning the response
return ResponseBuilder.from_diagram_result(result)

View File

@@ -0,0 +1,62 @@
"""Route for diagram generation from Kubernetes manifests."""
from flask import Blueprint, request
from services import generate_from_manifest
from utils import InputValidator, ResponseBuilder
from .utils import compact_for_log, log_to_csv
manifest_bp = Blueprint('manifest', __name__)
@manifest_bp.route('/api/generate-diagram', methods=['POST'])
def generate_diagram():
"""Diagram generation from a Kubernetes manifest."""
data = request.get_json()
manifest_content = data.get('manifest', '')
output_format = (data.get('outputFormat') or 'png').lower()
extra_args = data.get('extraArgs', '')
without_namespace = data.get('withoutNamespace', False)
# Log to CSV only
client_ip = request.remote_addr
route = request.path
params = (
f"format={output_format};"
f"extraArgs={compact_for_log(extra_args)};"
f"withoutNamespace={without_namespace};"
f"manifest={compact_for_log(manifest_content)}"
)
log_to_csv(client_ip, route, params)
# Manifest validation
is_valid, error_msg = InputValidator.validate_manifest(manifest_content)
if not is_valid:
return ResponseBuilder.validation_error("manifest", error_msg)
# Verify it doesn't look like a Helmfile
if InputValidator.looks_like_helmfile(manifest_content):
return ResponseBuilder.error(
"This looks like a Helmfile. Please use the HelmFile tab for this content."
)
# Output format validation
is_valid, error_msg = InputValidator.validate_output_format(output_format)
if not is_valid:
return ResponseBuilder.validation_error("outputFormat", error_msg)
# Extra arguments validation
is_valid, error_msg = InputValidator.validate_extra_args(extra_args)
if not is_valid:
return ResponseBuilder.validation_error("extraArgs", error_msg)
# Generate diagram through service
result = generate_from_manifest(
manifest_content=manifest_content,
output_format=output_format,
extra_args=extra_args,
without_namespace=without_namespace
)
# Returning the response
return ResponseBuilder.from_diagram_result(result)

View File

@@ -0,0 +1,43 @@
"""Route for submitting user feedback."""
from flask import request, Blueprint
import logging
from config import Config
from utils import ResponseBuilder, logger
from .utils import log_to_csv
submit_bp = Blueprint('submit', __name__)
@submit_bp.route('/api/submit-feedback', methods=['POST'])
def submit_feedback():
"""Submit user feedback."""
data = request.get_json()
note = data.get("note", "")
comment = data.get("comment", "")
diagram_type = data.get("diagramType", "unknown")
# Log to CSV only
client_ip = request.remote_addr
log_to_csv(client_ip, "Feedback", f"type={diagram_type};note={note}")
if note or comment:
try:
with open(Config.FEEDBACK_FILE, "a", encoding="utf-8") as f:
f.write(f"[{diagram_type.upper()}]\nNote: {note}\nCommentaire: {comment}\n\n")
return ResponseBuilder.success(
message="Feedback submitted successfully. Thank you!"
)
except Exception as e:
# Log l'erreur dans le CSV
csv_logger = logging.getLogger(Config.LOGGER_NAME)
csv_logger.error(f"Error writing feedback: {e}")
return ResponseBuilder.error(
"Failed to save feedback. Please try again.",
status_code=500
)
return ResponseBuilder.validation_error(
"feedback",
"Feedback must contain at least a note or a comment."
)

View File

@@ -0,0 +1,37 @@
"""Functions utils for routes."""
from constants import MAX_LOG_LENGTH
def compact_for_log(value: str, maxlen: int = MAX_LOG_LENGTH) -> str:
"""
Compress a string for the logs (escape n/ r).
Args:
value: Value to be compressed
maxlen: Maximum length
Returns:
str: Compacted String
"""
if value is None:
return ""
s = str(value).replace("\n", "\\n").replace("\r", "\\r")
if len(s) <= maxlen:
return s
return s[:maxlen] + f"...<+{len(s)-maxlen} chars>"
def log_to_csv(client_ip: str, route: str, params: str):
"""
Legacy function kept for backward compatibility.
Note: Logging is now handled centrally in app.py using Apache Combined Log Format
which is compatible with GoAccess and other log analysis tools.
Args:
client_ip: Not used (IP obtained from request)
route: Not used (obtained from request)
params: Not used (logging is done in after_request)
"""
# No-op: logging is handled by app.py after_request in Apache Combined Log Format
pass

View File

@@ -0,0 +1,15 @@
"""Package contains all services for diagram generation."""
from .models import DiagramResult
from .file_manager import FileManager
from .manifestService import generate_from_manifest
from .helmService import generate_from_helm
from .helmfileService import generate_from_helmfile
__all__ = [
'DiagramResult',
'FileManager',
'generate_from_manifest',
'generate_from_helm',
'generate_from_helmfile'
]

View File

@@ -0,0 +1,100 @@
"""Temporary file management."""
import os
import tempfile
from typing import Optional
from contextlib import contextmanager
class FileManager:
"""Temporary file manager."""
@staticmethod
@contextmanager
def create_temp_file(content: str, suffix: str = '.yaml', mode: str = 'w'):
"""
Create a temporary file with the given content.
Args:
content: Content to be written in the file
suffix: File suffix (extension)
mode: File opening mode
Yields:
str: Temporary file path created
"""
temp_file = None
try:
with tempfile.NamedTemporaryFile(mode=mode, delete=False, suffix=suffix) as f:
if mode == 'w':
f.write(content)
else:
f.write(content.encode('utf-8'))
temp_file = f.name
yield temp_file
finally:
if temp_file and os.path.exists(temp_file):
try:
os.remove(temp_file)
except OSError:
pass
@staticmethod
def cleanup_files(*file_paths: str) -> None:
"""
Safely deletes the specified files.
Args:
*file_paths: Paths of the files to be deleted
"""
for file_path in file_paths:
if file_path and os.path.exists(file_path):
try:
os.remove(file_path)
except OSError:
pass
@staticmethod
def get_output_paths(base_path: str, output_format: str) -> tuple[str, str]:
"""
Generates the output paths for a given format.
Args:
base_path: Base path (without extension)
output_format: Requested output format
Returns:
tuple: (requested format_path, fallback png_path)
"""
base_without_ext = os.path.splitext(base_path)[0]
requested_output = f"{base_without_ext}.{output_format}"
png_output = f"{base_without_ext}.png"
return requested_output, png_output
@staticmethod
def find_output_file(requested_path: str, fallback_path: str) -> Optional[tuple[str, str]]:
"""
Find the generated output file.
Args:
requested_path: File path in the requested format
fallback_path: Fallback file path (PNG)
Returns:
tuple: (file_path, format) or None if no file found
"""
if os.path.exists(requested_path):
format_ext = os.path.splitext(requested_path)[1].lstrip('.')
return requested_path, format_ext
elif os.path.exists(fallback_path):
return fallback_path, "png"
return None
@staticmethod
def read_file_content(file_path: str, binary: bool = True) -> bytes | str:
"""
Reads the contents of a file.
Args:
file_path: Path of the file to read
binary: If True, reads in binary mode
Returns:
File content (bytes or str)
"""
mode = "rb" if binary else "r"
with open(file_path, mode) as f:
return f.read()
@staticmethod
def get_base_name_from_path(file_path: str) -> str:
"""
Extract the base name of a file path (without extension).
Args:
file_path: File path
Returns:
Base name without extension
"""
return os.path.splitext(os.path.basename(file_path))[0]

View File

@@ -0,0 +1,137 @@
"""Service for generating diagrams from Helm charts."""
import subprocess
import os
from urllib.parse import urlparse
from constants import MIME_TYPES
from .models import DiagramResult
from .file_manager import FileManager
from .utils import parse_extra_args, has_fatal_error, encode_content
def generate_from_helm(
chart_url: str,
output_format: str = "png",
extra_args: str = ""
) -> DiagramResult:
"""
Generate a diagram from a Helm chart.
Args:
chart_url: Helm chart URL
output_format: Output format
extra_args: Additional arguments
Returns:
DiagramResult: Result of the generation
"""
# Extraction du nom de base
parsed = urlparse(chart_url)
base_name = os.path.basename(parsed.path).replace(".tgz", "").replace(".tar.gz", "")
# Pour les URLs OCI
if chart_url.startswith('oci://'):
base_name = chart_url.rstrip('/').split('/')[-1]
requested_output = os.path.abspath(f"{base_name}.{output_format}")
png_output = os.path.abspath(f"{base_name}.png")
try:
# Command uses helm-diagrams instead of helm
cmd = ["helm-diagrams", chart_url, "-o", f"{base_name}.{output_format}"]
if extra_args.strip():
cmd.extend(parse_extra_args(extra_args))
# Execution
proc = subprocess.run(cmd, check=False, capture_output=True, text=True)
stdout_output = proc.stdout or ""
stderr_output = proc.stderr or ""
# First we verify if there was an error before file exist
has_error = proc.returncode != 0 or has_fatal_error(stdout_output, stderr_output)
# Second we verify if there was an error in the stderr output
if "Error:" in stderr_output or "execution error" in stderr_output.lower():
has_error = True
if has_error:
FileManager.cleanup_files(requested_output, png_output)
# logs for all errors
error_details = []
if "not found" in stderr_output.lower() or "404" in stderr_output:
error_details.append("Chart not found. Please verify the repository URL and chart name.")
if "could not download" in stderr_output.lower():
error_details.append("Could not download the chart. Check the URL and your network connection.")
if "authentication" in stderr_output.lower() or "unauthorized" in stderr_output.lower():
error_details.append("Authentication required or access denied.")
if "is not a valid chart repository" in stderr_output.lower():
error_details.append("The URL is not a valid Helm chart repository.")
if "repo not found" in stderr_output.lower():
error_details.append("Repository not found. Make sure the URL points to a valid Helm repository.")
if "execution error" in stderr_output.lower():
error_details.append("Helm chart has configuration errors. Check the stderr output below for details.")
if "you must provide" in stderr_output.lower():
error_details.append("Missing required configuration values in the chart.")
main_error = " ".join(error_details) if error_details else "helm-diagrams failed to generate the diagram."
return DiagramResult(
success=False,
error=main_error,
command=" ".join(cmd),
stdout=stdout_output,
stderr=stderr_output
)
# Search for the output file
output_info = FileManager.find_output_file(requested_output, png_output)
if not output_info:
return DiagramResult(
success=False,
error=f"Output file not found (looked for {os.path.basename(requested_output)} and {os.path.basename(png_output)}).",
command=" ".join(cmd),
stdout=stdout_output,
stderr=stderr_output
)
output_file, produced_format = output_info
note = ""
if produced_format == "png" and output_format != "png":
note = f"Requested format '{output_format}' is not available from helm-diagrams. Returned PNG instead."
content = FileManager.read_file_content(output_file, binary=True)
encoded = encode_content(content, produced_format)
# Cleaning
FileManager.cleanup_files(requested_output, png_output)
message = (note + " " if note else "") + "Helm diagram successfully generated."
return DiagramResult(
success=True,
diagram=encoded,
mime_type=MIME_TYPES.get(produced_format, "application/octet-stream"),
filename=f"{base_name}.{produced_format}",
message=message.strip(),
command=" ".join(cmd),
stdout=stdout_output,
stderr=stderr_output
)
except ValueError as e:
FileManager.cleanup_files(requested_output, png_output)
return DiagramResult(
success=False,
error=str(e),
command=" ".join(cmd) if 'cmd' in locals() else None
)
except Exception as e:
FileManager.cleanup_files(requested_output, png_output)
return DiagramResult(
success=False,
error=f"Internal error: {e}",
command=" ".join(cmd) if 'cmd' in locals() else None
)

View File

@@ -0,0 +1,121 @@
"""Service for generating diagrams from Helmfiles."""
import subprocess
import os
from constants import MIME_TYPES
from .models import DiagramResult
from .file_manager import FileManager
from .utils import parse_extra_args, has_fatal_error, encode_content
def generate_from_helmfile(
helmfile_content: str,
output_format: str = "png",
extra_args: str = "",
without_namespace: bool = False
) -> DiagramResult:
"""
Generate a diagram from a Helmfile.
Args:
helmfile_content: Contents of the Helmfile
output_format: Output format
extra_args: Additional arguments
without_namespace: Hide namespaces
Returns:
DiagramResult: Result of the generation
"""
with FileManager.create_temp_file(helmfile_content, suffix=".yaml", mode='wb') as temp_helmfile_path:
output_path = temp_helmfile_path + f".{output_format}"
try:
# Command helmfile template
template_cmd = ["helmfile", "template", "-f", temp_helmfile_path]
template_proc = subprocess.Popen(
template_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
helm_output, helm_err = template_proc.communicate()
if template_proc.returncode != 0 or has_fatal_error("", helm_err):
FileManager.cleanup_files(output_path)
return DiagramResult(
success=False,
error="Helmfile template failed. See command output below.",
command=" ".join(template_cmd),
stdout="",
stderr=helm_err or ""
)
# Command kube-diagrams
cmd = ["kube-diagrams", "-", "-o", output_path]
if without_namespace:
cmd.append("--without-namespace")
if extra_args.strip():
cmd.extend(parse_extra_args(extra_args))
kube_proc = subprocess.run(
cmd,
input=helm_output,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
stdout_output = kube_proc.stdout or ""
stderr_output = kube_proc.stderr or ""
if kube_proc.returncode != 0 or has_fatal_error(stdout_output, stderr_output):
FileManager.cleanup_files(output_path)
return DiagramResult(
success=False,
error="kube-diagrams failed",
command=f"{' '.join(template_cmd)} | {' '.join(cmd)}",
stdout=stdout_output,
stderr=stderr_output
)
if not os.path.exists(output_path):
return DiagramResult(
success=False,
error=f"Output file not found: {output_path}",
command=f"{' '.join(template_cmd)} | {' '.join(cmd)}",
stdout=stdout_output,
stderr=stderr_output
)
content = FileManager.read_file_content(output_path, binary=True)
encoded = encode_content(content, output_format)
# Cleaning
FileManager.cleanup_files(output_path)
return DiagramResult(
success=True,
diagram=encoded,
mime_type=MIME_TYPES.get(output_format, "application/octet-stream"),
filename=f"helmfile-diagram.{output_format}",
message="Helmfile diagram successfully generated.",
command=f"{' '.join(template_cmd)} | {' '.join(cmd)}",
stdout=stdout_output,
stderr=stderr_output
)
except ValueError as e:
FileManager.cleanup_files(output_path)
return DiagramResult(
success=False,
error=str(e),
command=" ".join(cmd) if 'cmd' in locals() else None
)
except Exception as e:
FileManager.cleanup_files(output_path)
return DiagramResult(
success=False,
error=str(e),
command=" ".join(cmd) if 'cmd' in locals() else None
)

View File

@@ -0,0 +1,99 @@
"""Service for generating diagrams from Kubernetes manifests."""
import subprocess
from constants import MIME_TYPES
from .models import DiagramResult
from .file_manager import FileManager
from .utils import parse_extra_args, has_fatal_error, encode_content
def generate_from_manifest(
manifest_content: str,
output_format: str = "png",
extra_args: str = "",
without_namespace: bool = False
) -> DiagramResult:
"""
Generate a diagram from a Kubernetes manifest.
Args:
manifest_content: Content of the manifest
output_format: Output format (png, svg, etc.)
extra_args: Additional arguments for kube-diagrams
without_namespace: Hide namespaces
Returns:
DiagramResult: Result of the generation
"""
with FileManager.create_temp_file(manifest_content, suffix='.yaml') as tmp_manifest:
base_name = FileManager.get_base_name_from_path(tmp_manifest)
requested_output, png_output = FileManager.get_output_paths(tmp_manifest, output_format)
try:
# Command
cmd = ["kube-diagrams", tmp_manifest, "-o", requested_output]
if without_namespace:
cmd.append("--without-namespace")
if extra_args.strip():
cmd.extend(parse_extra_args(extra_args))
# Execution
proc = subprocess.run(cmd, check=False, capture_output=True, text=True)
stdout_output = proc.stdout or ""
stderr_output = proc.stderr or ""
# Error verification
if proc.returncode != 0 or has_fatal_error(stdout_output, stderr_output):
FileManager.cleanup_files(requested_output, png_output)
return DiagramResult(
success=False,
error="KubeDiagrams failed. See command output below.",
command=" ".join(cmd),
stdout=stdout_output,
stderr=stderr_output
)
# Output file verification
output_info = FileManager.find_output_file(requested_output, png_output)
if not output_info:
return DiagramResult(
success=False,
error=f"Output file not found (looked for {requested_output} and {png_output}).",
command=" ".join(cmd),
stdout=stdout_output,
stderr=stderr_output
)
output_file, produced_format = output_info
content = FileManager.read_file_content(output_file, binary=True)
encoded = encode_content(content, produced_format)
# Cleaning
FileManager.cleanup_files(requested_output, png_output)
return DiagramResult(
success=True,
diagram=encoded,
mime_type=MIME_TYPES.get(produced_format, "application/octet-stream"),
filename=f"{base_name}.{produced_format}",
message="Diagram successfully generated.",
command=" ".join(cmd),
stdout=stdout_output,
stderr=stderr_output
)
except ValueError as e:
FileManager.cleanup_files(requested_output, png_output)
return DiagramResult(
success=False,
error=str(e),
command=" ".join(cmd) if 'cmd' in locals() else None
)
except Exception as e:
FileManager.cleanup_files(requested_output, png_output)
return DiagramResult(
success=False,
error=f"Internal error: {e}",
command=" ".join(cmd) if 'cmd' in locals() else None
)

View File

@@ -0,0 +1,43 @@
"""Service Data Model"""
from typing import Optional
class DiagramResult:
"""Data model for the diagram result."""
def __init__(
self,
success: bool,
diagram: Optional[str] = None,
mime_type: Optional[str] = None,
filename: Optional[str] = None,
message: Optional[str] = None,
error: Optional[str] = None,
command: Optional[str] = None,
stdout: Optional[str] = None,
stderr: Optional[str] = None
):
self.success = success
self.diagram = diagram
self.mime_type = mime_type
self.filename = filename
self.message = message
self.error = error
self.command = command
self.stdout = stdout
self.stderr = stderr
def to_dict(self) -> dict:
"""Converts the DiagramResult to a dictionary."""
result = {
"command": self.command,
"stdout": self.stdout or "",
"stderr": self.stderr or ""
}
if self.success:
result.update({
"diagram": self.diagram,
"mimeType": self.mime_type,
"filename": self.filename,
"message": self.message
})
else:
result["error"] = self.error
return result

View File

@@ -0,0 +1,57 @@
"""Utilitaires pour les services de génération de diagrammes."""
import base64
import shlex
from constants import TEXT_FORMATS
def has_fatal_error(stdout_txt: str, stderr_txt: str) -> bool:
"""
Vérifie si la sortie contient une erreur fatale.
Args:
stdout_txt: Sortie standard
stderr_txt: Sortie d'erreur
Returns:
bool: True si erreur fatale détectée
"""
return ("error:" in (stdout_txt or "").lower()) or ("error:" in (stderr_txt or "").lower())
def parse_extra_args(extra_args: str) -> list[str]:
"""
Parse les arguments supplémentaires.
Args:
extra_args: Arguments supplémentaires en string
Returns:
list[str]: Liste des arguments parsés
Raises:
ValueError: Si les arguments sont invalides
"""
if not extra_args or not extra_args.strip():
return []
try:
return shlex.split(extra_args.strip())
except Exception as e:
raise ValueError(f"Invalid extraArgs: {e}")
def encode_content(content: bytes, output_format: str) -> str:
"""
Encode le contenu en base64 ou UTF-8 selon le format.
Args:
content: Contenu à encoder
output_format: Format de sortie
Returns:
str: Contenu encodé
"""
if output_format in TEXT_FORMATS:
return content.decode("utf-8")
return base64.b64encode(content).decode("utf-8")

View File

@@ -0,0 +1,17 @@
"""Package utils."""
from .logger import AppLogger, get_app_logger
from .validators import InputValidator, ValidationError
from .response_builder import ResponseBuilder
from .access_logger import get_real_ip, log_request, log_request_compact
__all__ = [
'AppLogger',
'get_app_logger',
'InputValidator',
'ValidationError',
'ResponseBuilder',
'get_real_ip',
'log_request',
'log_request_compact'
]

View File

@@ -0,0 +1,283 @@
"""access logging for Flask application."""
import logging
from datetime import datetime
from flask import request, g
from typing import Optional
from config import Config
def is_valid_ip(ip: str) -> bool:
"""
Check if the IP address is valid and not a placeholder.
Args:
ip: IP address string to validate
Returns:
bool: True if IP is valid, False otherwise
"""
if not ip:
return False
ip = ip.strip()
# List of invalid placeholder values (not real IPs)
invalid_values = [
'',
'-',
'(null)',
'null',
'None',
'unknown',
]
if ip.lower() in [v.lower() for v in invalid_values]:
return False
return True
def normalize_ip(ip: str) -> str:
"""
Normalize IP address to IPv4 format when possible.
Converts IPv6 localhost (::1) to IPv4 (127.0.0.1).
Args:
ip: IP address string
Returns:
str: Normalized IP address
"""
if not ip:
return '-'
ip = ip.strip()
# Convert IPv6 localhost to IPv4
if ip == '::1':
return '127.0.0.1'
# Convert IPv6-mapped IPv4 addresses (::ffff:192.168.1.1 -> 192.168.1.1)
if ip.startswith('::ffff:'):
return ip[7:]
return ip
def get_real_ip() -> str:
"""
Get the real IP address of the client, handling proxies and load balancers.
When using ProxyFix middleware (Config.BEHIND_PROXY=True), request.remote_addr
is automatically set to the real client IP from X-Forwarded-For headers.
For additional safety, we also check common proxy headers manually:
1. X-Forwarded-For (most common with reverse proxies)
2. X-Real-IP (nginx)
3. CF-Connecting-IP (Cloudflare)
4. True-Client-IP (Akamai and some CDNs)
5. request.remote_addr (fallback / already fixed by ProxyFix)
Returns:
str: The real IP address of the client (normalized to IPv4 when possible)
"""
# X-Forwarded-For can contain multiple IPs: "client, proxy1, proxy2"
# The first one is the original client
x_forwarded_for = request.headers.get('X-Forwarded-For')
if x_forwarded_for:
# Take the first IP in the chain (the original client)
ip = x_forwarded_for.split(',')[0].strip()
if is_valid_ip(ip):
return normalize_ip(ip)
# X-Real-IP is used by nginx
x_real_ip = request.headers.get('X-Real-IP')
if x_real_ip and is_valid_ip(x_real_ip):
return normalize_ip(x_real_ip.strip())
# Cloudflare specific header
cf_connecting_ip = request.headers.get('CF-Connecting-IP')
if cf_connecting_ip and is_valid_ip(cf_connecting_ip):
return normalize_ip(cf_connecting_ip.strip())
# Akamai and some CDNs
true_client_ip = request.headers.get('True-Client-IP')
if true_client_ip and is_valid_ip(true_client_ip):
return normalize_ip(true_client_ip.strip())
# X-Client-IP (some load balancers)
x_client_ip = request.headers.get('X-Client-IP')
if x_client_ip and is_valid_ip(x_client_ip):
return normalize_ip(x_client_ip.strip())
# Fallback to remote_addr (will be correct if ProxyFix is enabled)
remote_addr = request.remote_addr
if remote_addr and is_valid_ip(remote_addr):
return normalize_ip(remote_addr)
# Ultimate fallback
return '-'
def get_all_ip_headers() -> dict:
"""
Get all IP-related headers for debugging purposes.
Returns:
dict: Dictionary of all IP-related headers and their values
"""
headers = {
'remote_addr': request.remote_addr,
'X-Forwarded-For': request.headers.get('X-Forwarded-For'),
'X-Real-IP': request.headers.get('X-Real-IP'),
'CF-Connecting-IP': request.headers.get('CF-Connecting-IP'),
'True-Client-IP': request.headers.get('True-Client-IP'),
'X-Client-IP': request.headers.get('X-Client-IP'),
'X-Forwarded-Proto': request.headers.get('X-Forwarded-Proto'),
'X-Forwarded-Host': request.headers.get('X-Forwarded-Host'),
}
return {k: v for k, v in headers.items() if v is not None}
def get_user_agent() -> str:
"""
Get the User-Agent header.
Returns:
str: User-Agent string or '-' if not present
"""
return request.headers.get('User-Agent', '-')
def get_referer() -> str:
"""
Get the Referer header.
Returns:
str: Referer URL or '-' if not present
"""
return request.headers.get('Referer', '-')
def format_apache_log(
ip: str,
method: str,
path: str,
protocol: str,
status_code: int,
response_size: int,
referer: str,
user_agent: str,
request_time: Optional[float] = None
) -> str:
"""
Format log entry in Apache Combined Log Format with additional info.
Apache Combined Log Format:
IP - - [datetime] "METHOD PATH PROTOCOL" STATUS SIZE "REFERER" "USER-AGENT"
We add request time at the end for performance monitoring.
Args:
ip: Client IP address
method: HTTP method (GET, POST, etc.)
path: Request path
protocol: HTTP protocol version
status_code: HTTP status code
response_size: Response size in bytes
referer: Referer header
user_agent: User-Agent header
request_time: Request processing time in milliseconds (optional)
Returns:
str: Formatted log entry
"""
# Format datetime in Apache format: [10/Oct/2000:13:55:36 +0000]
now = datetime.now()
timestamp = now.strftime('[%d/%b/%Y:%H:%M:%S +0000]')
# Escape quotes in referer and user-agent
referer = referer.replace('"', '\\"')
user_agent = user_agent.replace('"', '\\"')
# Format: IP - - [datetime] "METHOD PATH PROTOCOL" STATUS SIZE "REFERER" "USER-AGENT"
log_line = (
f'{ip} - - {timestamp} '
f'"{method} {path} {protocol}" '
f'{status_code} {response_size} '
f'"{referer}" "{user_agent}"'
)
# Add request time if available
if request_time is not None:
log_line += f' {request_time:.2f}ms'
return log_line
def log_request(status_code: int, response_size: int = 0):
"""
Log an HTTP request in Apache Combined Log Format.
Args:
status_code: HTTP status code
response_size: Response size in bytes (default: 0)
"""
try:
ip = get_real_ip()
method = request.method
path = request.path
protocol = request.environ.get('SERVER_PROTOCOL', 'HTTP/1.1')
referer = get_referer()
user_agent = get_user_agent()
# Calculate request time if available
request_time = None
if hasattr(g, 'request_start_time'):
from time import time
request_time = (time() - g.request_start_time) * 1000 # Convert to ms
# Format and log
log_line = format_apache_log(
ip=ip,
method=method,
path=path,
protocol=protocol,
status_code=status_code,
response_size=response_size,
referer=referer,
user_agent=user_agent,
request_time=request_time
)
logger = logging.getLogger(Config.LOGGER_NAME)
logger.info(log_line)
except Exception as e:
# Don't let logging errors break the application
error_logger = logging.getLogger('app')
error_logger.error(f"Error logging request: {e}")
def log_request_compact(status_code: int, params_summary: str = ""):
"""
Log an HTTP request with a compact parameter summary (for backward compatibility).
This can be used for detailed parameter logging alongside the Apache-style log.
Args:
status_code: HTTP status code
params_summary: Compact summary of request parameters
"""
try:
ip = get_real_ip()
path = request.path
# Compact format: IP ; PATH ; PARAMS
log_line = f"{ip} ; {path} ; {params_summary}"
logger = logging.getLogger(Config.LOGGER_NAME)
logger.info(log_line)
except Exception as e:
error_logger = logging.getLogger('app')
error_logger.error(f"Error logging request: {e}")

View File

@@ -0,0 +1,108 @@
"""Configuration for application logging."""
import logging
import sys
from logging.handlers import RotatingFileHandler
from pathlib import Path
class AppLogger:
"""Logging manager for the application."""
_loggers = {}
@classmethod
def setup_logger(
cls,
name: str,
log_file: str = None,
level: int = logging.INFO,
max_bytes: int = 10 * 1024 * 1024, # 10MB
backup_count: int = 5
) -> logging.Logger:
"""
Configure and return a logger.
Args:
name: Name of the logger
log_file: Log File Path (optional)
level: Logging level
max_bytes: Maximum log file size before rotation
backup_count: Number of backup files to keep
Returns:
logging.Logger: Logger configured
"""
# To not recreate logger if already exist
if name in cls._loggers:
return cls._loggers[name]
logger = logging.getLogger(name)
logger.setLevel(level)
# Avoid adding multiple handlers to the same logger
if logger.handlers:
return logger
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# Console handler
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(level)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
# Handler file if needed
if log_file:
# Create directory if needed
log_path = Path(log_file)
log_path.parent.mkdir(parents=True, exist_ok=True)
file_handler = RotatingFileHandler(
log_file,
maxBytes=max_bytes,
backupCount=backup_count,
encoding='utf-8'
)
file_handler.setLevel(level)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
cls._loggers[name] = logger
return logger
@classmethod
def get_logger(cls, name: str) -> logging.Logger:
"""
Retrieve an existing logger or create a new one.
Args:
name: Name of the logger
Returns:
logging.Logger: Logger
"""
if name in cls._loggers:
return cls._loggers[name]
return cls.setup_logger(name)
def get_app_logger(name: str = None) -> logging.Logger:
"""
Helper function to obtain a logger.
Args:
name: Name of the logger (uses the name of the calling module by default)
Returns:
logging.Logger: Logger configured
"""
if name is None:
import inspect
frame = inspect.currentframe().f_back
name = frame.f_globals.get('__name__', 'app')
return AppLogger.get_logger(name)

View File

@@ -0,0 +1,172 @@
"""Http response builder."""
from typing import Any, Dict, Optional
from flask import jsonify, Response
class ResponseBuilder:
"""Http response builder."""
@staticmethod
def success(
data: Any = None,
message: str = "Success",
status_code: int = 200
) -> tuple[Response, int]:
"""
Create a standardized success response.
Args:
data: Data to be returned
message: Success message
status_code: HTTP status code
Returns:
tuple[Response, int]: Flask response and status code
"""
response = {
"success": True,
"message": message
}
if data is not None:
if isinstance(data, dict):
response.update(data)
else:
response["data"] = data
return jsonify(response), status_code
@staticmethod
def error(
error: str,
details: Optional[Dict[str, Any]] = None,
status_code: int = 400
) -> tuple[Response, int]:
"""
Creates a standard error response.
Args:
error: Error message
details: Additional details
status_code: HTTP status code
Returns:
tuple[Response, int]: Flask response and status code
"""
response = {
"success": False,
"error": error
}
if details:
response.update(details)
return jsonify(response), status_code
@staticmethod
def validation_error(
field: str,
message: str,
status_code: int = 400
) -> tuple[Response, int]:
"""
Creates a validation error response.
Args:
field: Field in error
message: Error message
status_code: HTTP status code
Returns:
tuple[Response, int]: Flask response and status code
"""
return ResponseBuilder.error(
error=message,
details={"field": field, "type": "validation_error"},
status_code=status_code
)
@staticmethod
def diagram_success(
diagram: str,
mime_type: str,
filename: str,
message: str = "Diagram successfully generated.",
command: str = None,
stdout: str = "",
stderr: str = ""
) -> tuple[Response, int]:
"""
Creates a success response for the diagram generation.
Args:
diagram: Content of the diagram (encoded)
mime_type: MIME type of the diagram
filename: File name
message: Success message
command: Command executed
stdout: Standard output
stderr: Error output
Returns:
tuple[Response, int]: Flask response and status code
"""
response_data = {
"diagram": diagram,
"mimeType": mime_type,
"filename": filename,
"message": message,
"command": command,
"stdout": stdout or "",
"stderr": stderr or ""
}
return ResponseBuilder.success(data=response_data, message=message, status_code=200)
@staticmethod
def diagram_error(
error: str,
command: str = None,
stdout: str = "",
stderr: str = "",
status_code: int = 400
) -> tuple[Response, int]:
"""
Creates an error response for diagram generation.
Args:
error: Error message
command: Command executed
stdout: Standard output
stderr: Error output
status_code: HTTP status code
Returns:
tuple[Response, int]: Flask response and status code
"""
details = {
"command": command,
"stdout": stdout or "",
"stderr": stderr or ""
}
return ResponseBuilder.error(
error=error,
details=details,
status_code=status_code
)
@staticmethod
def from_diagram_result(result) -> tuple[Response, int]:
"""
Create a response from a DiagramResult.
Args:
result: Instance of DiagramResult
Returns:
tuple[Response, int]: Flask response and status code
"""
status_code = 200 if result.success else 400
return jsonify(result.to_dict()), status_code

View File

@@ -0,0 +1,183 @@
"""Validation of user inputs."""
import re
from typing import Optional, Tuple
from constants import MANIFEST_RE, KIND_RE
class ValidationError(Exception):
"""Exception error validation."""
pass
class InputValidator:
"""Validator for user inputs."""
SUPPORTED_FORMATS = ['png', 'jpg', 'jpeg', 'gif', 'svg', 'pdf', 'dot', 'dot_json']
# Valid Pattern for url
HELM_URL_PATTERN = re.compile(
r'^(https?://|oci://|file://|[a-zA-Z0-9\-_]+/[a-zA-Z0-9\-_]+)'
)
@classmethod
def validate_manifest(cls, content: str) -> Tuple[bool, Optional[str]]:
"""
Validate a Kubernetes manifest content.
Args:
content: Manifest content
Returns:
Tuple[bool, Optional[str]]: (is_valid, error_message)
"""
if not content or not content.strip():
return False, "Manifest content cannot be empty."
# Verify minimum length
if len(content.strip()) < 10:
return False, "Manifest content is too short."
# Verify it looks like a manifest K8s
if not cls.looks_like_manifest(content):
return False, "Content does not appear to be a valid Kubernetes manifest (missing apiVersion or kind)."
return True, None
@classmethod
def validate_helmfile(cls, content: str) -> Tuple[bool, Optional[str]]:
"""
Validate a Helmfile content.
Args:
content: Content of a Helmfile
Returns:
Tuple[bool, Optional[str]]: (is_valid, error_message)
"""
if not content or not content.strip():
return False, "Helmfile content cannot be empty."
if len(content.strip()) < 10:
return False, "Helmfile content is too short."
# Verify it looks like a Helmfile
if not cls.looks_like_helmfile(content):
return False, "Content does not appear to be a valid Helmfile (missing typical Helmfile keys)."
return True, None
@classmethod
def validate_helm_chart_url(cls, url: str) -> Tuple[bool, Optional[str]]:
"""
Validate a Helm chart URL.
Args:
url: URL of the Helm chart
Returns:
Tuple[bool, Optional[str]]: (est_valide, message_erreur)
"""
if not url or not url.strip():
return False, "Chart URL cannot be empty."
url = url.strip()
# Verify the helm url pattern
if not cls.HELM_URL_PATTERN.match(url):
return False, "Invalid Helm chart URL format. Must start with http://, https://, oci://, file://, or be a chart reference."
return True, None
@classmethod
def validate_output_format(cls, format_str: str) -> Tuple[bool, Optional[str]]:
"""
Validate output format.
Args:
format_str: output format
Returns:
Tuple[bool, Optional[str]]: (is_valid, error_message)
"""
if not format_str:
return False, "Output format cannot be empty."
format_str = format_str.lower().strip()
if format_str not in cls.SUPPORTED_FORMATS:
return False, f"Unsupported output format '{format_str}'. Supported formats: {', '.join(cls.SUPPORTED_FORMATS)}"
return True, None
@classmethod
def validate_extra_args(cls, args: str) -> Tuple[bool, Optional[str]]:
"""
Validate extra args.
Args:
args: extra_args
Returns:
Tuple[bool, Optional[str]]: (is_valid, error_message)
"""
if not args or not args.strip():
return True, None # Les args vides sont valides
dangerous_chars = [';', '&', '|', '`', '$', '(', ')']
for char in dangerous_chars:
if char in args:
return False, f"Extra args contain dangerous character '{char}'"
return True, None
@staticmethod
def looks_like_manifest(text: str) -> bool:
"""
Heuristic to detect a Kubernetes manifest.
Args:
text: content that will be checked
Returns:
bool: True if it looks like a manifest
"""
if not text:
return False
t = text.strip()
return bool(MANIFEST_RE.search(t) and KIND_RE.search(t))
@staticmethod
def looks_like_helmfile(text: str) -> bool:
"""
Heuristic to detect a HelmFile.
Args:
text: Content that will be checked.
Returns:
bool: True if it looks like a Helmfile
"""
if not text:
return False
t = text.lower()
helmfile_keys = ["\nreleases:", "\nrepositories:", "\nhelmdefaults:", "\nenvironments:", "\ntemplates:"]
return any(key in t for key in helmfile_keys)
# TODO: Not used yet
@classmethod
def sanitize_filename(cls, filename: str) -> str:
"""
Clean a filename to make it safe.
Args:
filename: Filename to clean
Returns:
str: Filename cleaned
"""
safe_filename = re.sub(r'[^a-zA-Z0-9._-]', '_', filename)
# Length limit
if len(safe_filename) > 255:
safe_filename = safe_filename[:255]
return safe_filename

View File

@@ -0,0 +1,247 @@
<#
.Synopsis
Activate a Python virtual environment for the current PowerShell session.
.Description
Pushes the python executable for a virtual environment to the front of the
$Env:PATH environment variable and sets the prompt to signify that you are
in a Python virtual environment. Makes use of the command line switches as
well as the `pyvenv.cfg` file values present in the virtual environment.
.Parameter VenvDir
Path to the directory that contains the virtual environment to activate. The
default value for this is the parent of the directory that the Activate.ps1
script is located within.
.Parameter Prompt
The prompt prefix to display when this virtual environment is activated. By
default, this prompt is the name of the virtual environment folder (VenvDir)
surrounded by parentheses and followed by a single space (ie. '(.venv) ').
.Example
Activate.ps1
Activates the Python virtual environment that contains the Activate.ps1 script.
.Example
Activate.ps1 -Verbose
Activates the Python virtual environment that contains the Activate.ps1 script,
and shows extra information about the activation as it executes.
.Example
Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
Activates the Python virtual environment located in the specified location.
.Example
Activate.ps1 -Prompt "MyPython"
Activates the Python virtual environment that contains the Activate.ps1 script,
and prefixes the current prompt with the specified string (surrounded in
parentheses) while the virtual environment is active.
.Notes
On Windows, it may be required to enable this Activate.ps1 script by setting the
execution policy for the user. You can do this by issuing the following PowerShell
command:
PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
For more information on Execution Policies:
https://go.microsoft.com/fwlink/?LinkID=135170
#>
Param(
[Parameter(Mandatory = $false)]
[String]
$VenvDir,
[Parameter(Mandatory = $false)]
[String]
$Prompt
)
<# Function declarations --------------------------------------------------- #>
<#
.Synopsis
Remove all shell session elements added by the Activate script, including the
addition of the virtual environment's Python executable from the beginning of
the PATH variable.
.Parameter NonDestructive
If present, do not remove this function from the global namespace for the
session.
#>
function global:deactivate ([switch]$NonDestructive) {
# Revert to original values
# The prior prompt:
if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
}
# The prior PYTHONHOME:
if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
}
# The prior PATH:
if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
Remove-Item -Path Env:_OLD_VIRTUAL_PATH
}
# Just remove the VIRTUAL_ENV altogether:
if (Test-Path -Path Env:VIRTUAL_ENV) {
Remove-Item -Path env:VIRTUAL_ENV
}
# Just remove VIRTUAL_ENV_PROMPT altogether.
if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) {
Remove-Item -Path env:VIRTUAL_ENV_PROMPT
}
# Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
}
# Leave deactivate function in the global namespace if requested:
if (-not $NonDestructive) {
Remove-Item -Path function:deactivate
}
}
<#
.Description
Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
given folder, and returns them in a map.
For each line in the pyvenv.cfg file, if that line can be parsed into exactly
two strings separated by `=` (with any amount of whitespace surrounding the =)
then it is considered a `key = value` line. The left hand string is the key,
the right hand is the value.
If the value starts with a `'` or a `"` then the first and last character is
stripped from the value before being captured.
.Parameter ConfigDir
Path to the directory that contains the `pyvenv.cfg` file.
#>
function Get-PyVenvConfig(
[String]
$ConfigDir
) {
Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
# Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
$pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
# An empty map will be returned if no config file is found.
$pyvenvConfig = @{ }
if ($pyvenvConfigPath) {
Write-Verbose "File exists, parse `key = value` lines"
$pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
$pyvenvConfigContent | ForEach-Object {
$keyval = $PSItem -split "\s*=\s*", 2
if ($keyval[0] -and $keyval[1]) {
$val = $keyval[1]
# Remove extraneous quotations around a string value.
if ("'""".Contains($val.Substring(0, 1))) {
$val = $val.Substring(1, $val.Length - 2)
}
$pyvenvConfig[$keyval[0]] = $val
Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
}
}
}
return $pyvenvConfig
}
<# Begin Activate script --------------------------------------------------- #>
# Determine the containing directory of this script
$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
$VenvExecDir = Get-Item -Path $VenvExecPath
Write-Verbose "Activation script is located in path: '$VenvExecPath'"
Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
# Set values required in priority: CmdLine, ConfigFile, Default
# First, get the location of the virtual environment, it might not be
# VenvExecDir if specified on the command line.
if ($VenvDir) {
Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
}
else {
Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
$VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
Write-Verbose "VenvDir=$VenvDir"
}
# Next, read the `pyvenv.cfg` file to determine any required value such
# as `prompt`.
$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
# Next, set the prompt from the command line, or the config file, or
# just use the name of the virtual environment folder.
if ($Prompt) {
Write-Verbose "Prompt specified as argument, using '$Prompt'"
}
else {
Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
$Prompt = $pyvenvCfg['prompt'];
}
else {
Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)"
Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
$Prompt = Split-Path -Path $venvDir -Leaf
}
}
Write-Verbose "Prompt = '$Prompt'"
Write-Verbose "VenvDir='$VenvDir'"
# Deactivate any currently active virtual environment, but leave the
# deactivate function in place.
deactivate -nondestructive
# Now set the environment variable VIRTUAL_ENV, used by many tools to determine
# that there is an activated venv.
$env:VIRTUAL_ENV = $VenvDir
if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
Write-Verbose "Setting prompt to '$Prompt'"
# Set the prompt to include the env name
# Make sure _OLD_VIRTUAL_PROMPT is global
function global:_OLD_VIRTUAL_PROMPT { "" }
Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
function global:prompt {
Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
_OLD_VIRTUAL_PROMPT
}
$env:VIRTUAL_ENV_PROMPT = $Prompt
}
# Clear PYTHONHOME
if (Test-Path -Path Env:PYTHONHOME) {
Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
Remove-Item -Path Env:PYTHONHOME
}
# Add the venv to the PATH
Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"

View File

@@ -0,0 +1,70 @@
# This file must be used with "source bin/activate" *from bash*
# You cannot run it directly
deactivate () {
# reset old environment variables
if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
PATH="${_OLD_VIRTUAL_PATH:-}"
export PATH
unset _OLD_VIRTUAL_PATH
fi
if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
export PYTHONHOME
unset _OLD_VIRTUAL_PYTHONHOME
fi
# Call hash to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
hash -r 2> /dev/null
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
PS1="${_OLD_VIRTUAL_PS1:-}"
export PS1
unset _OLD_VIRTUAL_PS1
fi
unset VIRTUAL_ENV
unset VIRTUAL_ENV_PROMPT
if [ ! "${1:-}" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
}
# unset irrelevant variables
deactivate nondestructive
# on Windows, a path can contain colons and backslashes and has to be converted:
if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then
# transform D:\path\to\venv to /d/path/to/venv on MSYS
# and to /cygdrive/d/path/to/venv on Cygwin
export VIRTUAL_ENV=$(cygpath /home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv)
else
# use the path as-is
export VIRTUAL_ENV=/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv
fi
_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/"bin":$PATH"
export PATH
# unset PYTHONHOME if set
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
# could use `if (set -u; : $PYTHONHOME) ;` in bash
if [ -n "${PYTHONHOME:-}" ] ; then
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
unset PYTHONHOME
fi
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
_OLD_VIRTUAL_PS1="${PS1:-}"
PS1='(venv) '"${PS1:-}"
export PS1
VIRTUAL_ENV_PROMPT='(venv) '
export VIRTUAL_ENV_PROMPT
fi
# Call hash to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
hash -r 2> /dev/null

View File

@@ -0,0 +1,27 @@
# This file must be used with "source bin/activate.csh" *from csh*.
# You cannot run it directly.
# Created by Davide Di Blasi <davidedb@gmail.com>.
# Ported to Python 3.3 venv by Andrew Svetlov <andrew.svetlov@gmail.com>
alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate'
# Unset irrelevant variables.
deactivate nondestructive
setenv VIRTUAL_ENV /home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv
set _OLD_VIRTUAL_PATH="$PATH"
setenv PATH "$VIRTUAL_ENV/"bin":$PATH"
set _OLD_VIRTUAL_PROMPT="$prompt"
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
set prompt = '(venv) '"$prompt"
setenv VIRTUAL_ENV_PROMPT '(venv) '
endif
alias pydoc python -m pydoc
rehash

View File

@@ -0,0 +1,69 @@
# This file must be used with "source <venv>/bin/activate.fish" *from fish*
# (https://fishshell.com/). You cannot run it directly.
function deactivate -d "Exit virtual environment and return to normal shell environment"
# reset old environment variables
if test -n "$_OLD_VIRTUAL_PATH"
set -gx PATH $_OLD_VIRTUAL_PATH
set -e _OLD_VIRTUAL_PATH
end
if test -n "$_OLD_VIRTUAL_PYTHONHOME"
set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
set -e _OLD_VIRTUAL_PYTHONHOME
end
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
set -e _OLD_FISH_PROMPT_OVERRIDE
# prevents error when using nested fish instances (Issue #93858)
if functions -q _old_fish_prompt
functions -e fish_prompt
functions -c _old_fish_prompt fish_prompt
functions -e _old_fish_prompt
end
end
set -e VIRTUAL_ENV
set -e VIRTUAL_ENV_PROMPT
if test "$argv[1]" != "nondestructive"
# Self-destruct!
functions -e deactivate
end
end
# Unset irrelevant variables.
deactivate nondestructive
set -gx VIRTUAL_ENV /home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv
set -gx _OLD_VIRTUAL_PATH $PATH
set -gx PATH "$VIRTUAL_ENV/"bin $PATH
# Unset PYTHONHOME if set.
if set -q PYTHONHOME
set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
set -e PYTHONHOME
end
if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
# fish uses a function instead of an env var to generate the prompt.
# Save the current fish_prompt function as the function _old_fish_prompt.
functions -c fish_prompt _old_fish_prompt
# With the original prompt function renamed, we can override with our own.
function fish_prompt
# Save the return status of the last command.
set -l old_status $status
# Output the venv prompt; color taken from the blue of the Python logo.
printf "%s%s%s" (set_color 4B8BBE) '(venv) ' (set_color normal)
# Restore the return status of the previous command.
echo "exit $old_status" | .
# Output the original/"old" prompt.
_old_fish_prompt
end
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
set -gx VIRTUAL_ENV_PROMPT '(venv) '
end

View File

@@ -0,0 +1,8 @@
#!/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from diagrams.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
webapp/backend/venv/bin/flask Executable file
View File

@@ -0,0 +1,8 @@
#!/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from flask.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -0,0 +1,8 @@
#!/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from gunicorn.app.wsgiapp import run
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(run())

View File

@@ -0,0 +1,136 @@
#!/bin/bash
# helm-diagrams: A script to generate a diagram of an Helm chart
# using kube-diagrams from the output of 'helm template <name> <chart>'
# Check if kube-diagrams is installed
if ! command -v kube-diagrams &>/dev/null; then
echo "Error: kube-diagrams is not installed. Please install it first."
exit 1
fi
# Check if helm is installed
if ! command -v helm &>/dev/null; then
echo "Error: helm is not installed. Please install it first."
exit 1
fi
# Display help message
show_help() {
echo "Usage: helm-diagrams <helm-chart-url> [OPTIONS] [FLAGS]"
echo ""
echo "A script to generate a diagram of an Helm chart using kube-diagrams."
echo ""
echo "Options:"
echo " -o, --output <file> Specify the output file for the diagram"
echo " -f, --format <format> Specify the output format (e.g., png, svg)"
echo " --embed-all-icons Embed all icons into svg or dot_json output diagrams"
echo " -c, --config <file> Specify the custom kube-diagrams configuration file"
echo " -h, --help Display this help message"
echo ""
echo "Any flag supported by helm template, e.g.:"
echo " -g, --generate-name Generate the name (and omit the NAME parameter)"
echo " --include-crds Include CRDs in the templated output"
echo " -l, --labels stringToString Labels that would be added to release metadata. Should be divided by comma. (default [])"
echo " --name-template string Specify template used to name the release"
echo " --set stringArray Set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)"
echo " --set-file stringArray Set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)"
echo " --set-json stringArray Set JSON values on the command line (can specify multiple or separate values with commas: key1=jsonval1,key2=jsonval2)"
echo " --set-literal stringArray Set a literal STRING value on the command line"
echo " --set-string stringArray Set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)"
echo " -f, --values strings Specify values in a YAML file or a URL (can specify multiple)"
echo " --version string Specify a version constraint for the chart version to use. This constraint can be a specific tag (e.g. 1.1.1) or it may reference a valid range (e.g. ^2.0.0). If this is not specified, the latest version is used"
echo ""
echo "Examples:"
echo " helm-diagrams https://charts.jetstack.io/cert-manager -o diagram.png"
echo " helm-diagrams https://charts.jetstack.io/cert-manager --set crds.enabled=true -o cert-manager.png"
echo " helm-diagrams oci://ghcr.io/argoproj/argo-helm/argo-cd -f svg"
echo " helm-diagrams --help"
exit 0
}
# Initialize variables
HELM_CHART_URL=""
HELM_ARGS=()
KUBE_DIAGRAMS_ARGS=("-" "--without-namespace") # Default to stdin indicator
# Use the KubeDiagrams custom configuration if exist.
KD_CC="KubeDiagrams.yaml"
if [ -e $KD_CC ]
then
KUBE_DIAGRAMS_ARGS+=("--config" "$KD_CC")
fi
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-h | --help)
show_help
;;
-o | --output | -f | --format | -c | --config)
KUBE_DIAGRAMS_ARGS+=("$1")
if [[ -n "$2" ]]; then
KUBE_DIAGRAMS_ARGS+=("$2")
shift 2
else
echo "Error: $1 requires a value!"
exit 64
fi
;;
--embed-all-icons)
KUBE_DIAGRAMS_ARGS+=("$1")
shift
;;
*)
if [ -z "${HELM_CHART_URL}" ]; then
HELM_CHART_URL=$1
repository=$(dirname ${HELM_CHART_URL})
name=$(basename ${HELM_CHART_URL})
KUBE_DIAGRAMS_ARGS+=("--output" "${name}")
else
HELM_ARGS+=("$1")
fi
shift
;;
esac
done
# Check if any Helm chart url was specified
if [ -z "${HELM_CHART_URL}" ]; then
echo "Error: At least one Helm chart URL must be specified!"
exit 64
fi
echo Download ${HELM_CHART_URL}...
if [[ ${repository} == oci* ]]; then
# Deal with OCI registries.
# Execute helm and pipe to kube-diagrams with arguments
helm template ${name} ${HELM_CHART_URL} "${HELM_ARGS[@]}" | kube-diagrams "${KUBE_DIAGRAMS_ARGS[@]}"
EXIT_CODE=$?
elif [[ ${repository} == http* ]]; then
# Deal with HTTP registries.
# Add a Helm repository.
rid=helm-diagrams-repo
helm repo add $rid $repository --force-update >/dev/null
# Execute helm and pipe to kube-diagrams with arguments
helm template ${name} $rid/${name} "${HELM_ARGS[@]}" | kube-diagrams "${KUBE_DIAGRAMS_ARGS[@]}"
EXIT_CODE=$?
# Remove the Helm repository.
helm repo remove $rid >/dev/null
else
# Deal with local charts
# Execute helm and pipe to kube-diagrams with arguments
helm template ${name} ${repository}/${name} "${HELM_ARGS[@]}" | kube-diagrams -o local-$name "${KUBE_DIAGRAMS_ARGS[@]}"
EXIT_CODE=$?
fi
if [[ $EXIT_CODE -eq 0 ]]; then
echo "Diagram generated successfully"
else
echo "Error: Failed to generate diagram!"
exit 1
fi

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@@ -0,0 +1,8 @@
#!/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from identify.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,689 @@
# Configuration of kube-diagrams
default_namespace: default
edges:
REFERENCE:
color: black
REFERENCE-UP:
color: black
direction: up
SELECTOR:
color: black
style: dashed
SELECTOR-UP:
color: black
style: dashed
direction: up
CONTROLLED_BY:
xlabel: controller
color: black
style: dotted
OWNER:
color: black
style: dotted
COMMUNICATION:
color: brown
DEPENDENCE:
color: darkgrey
INVISIBLE:
color: transparent
style: invisible
direction: up
clusters:
- label: app.kubernetes.io/instance
title: "K8s Instance: {}"
recommended: true
graph_attr:
bgcolor: "#E5F5FD"
- label: release
title: "Release: {}"
recommended: false
graph_attr:
bgcolor: "#E5F5FD"
- label: helm.sh/chart
title: "Helm Chart: {}"
recommended: true
graph_attr:
bgcolor: "#EBF3E7"
- label: chart
title: "Chart: {}"
recommended: false
graph_attr:
bgcolor: "#EBF3E7"
- label: app.kubernetes.io/name
title: "K8s Application: {}"
recommended: true
graph_attr:
bgcolor: "#ECE8F6"
- label: app
title: "Application: {}"
recommended: false
graph_attr:
bgcolor: "#ECE8F6"
- label: tier
title: "Tier: {}"
recommended: false
graph_attr:
bgcolor: "#ECE8F6"
- label: app.kubernetes.io/component
title: "K8s Component: {}"
recommended: true
graph_attr:
bgcolor: "#FDF7E3"
- label: component
title: "Component: {}"
recommended: false
graph_attr:
bgcolor: "#FDF7E3"
- label: service
title: "Microservice: {}"
recommended: false
graph_attr:
bgcolor: "#FDF7E3"
- label: rbac.authorization.k8s.io/aggregate-to-admin
title: "Admin ClusterRole Aggregation"
recommended: true
graph_attr:
bgcolor: transparent
- label: rbac.authorization.k8s.io/aggregate-to-edit
title: "Edit ClusterRole Aggregation"
recommended: true
graph_attr:
bgcolor: transparent
- label: rbac.authorization.k8s.io/aggregate-to-view
title: "View ClusterRole Aggregation"
recommended: true
graph_attr:
bgcolor: transparent
- annotation: helm.sh/hook
title: "{}"
recommended: true
graph_attr:
bgcolor: "#EBF3E7"
style: dotted,rounded
nodes:
APIService/apiregistration.k8s.io/v1:
scope: Cluster
custom_icon: $KD/icons/apiservice.png
edges: |
service = query_path(resource, "spec.service")
if service is not None:
edges.add_edge_to(
"spec.service",
service['name'],
service['namespace'],
"Service",
"v1",
"REFERENCE"
)
APIService/apiregistration.k8s.io/v1beta1: APIService/apiregistration.k8s.io/v1
ClusterRole/rbac.authorization.k8s.io/v1:
scope: Cluster
diagram_node_classname: diagrams.k8s.rbac.CRole
edges: |
for idx, clusterRoleSelector in enumerate(query_path(resource, "aggregationRule.clusterRoleSelectors", [])):
edges.add_all_resources_matching_labels(
"ClusterRole",
f"aggregationRule.clusterRoleSelectors[{idx}]",
match_labels=clusterRoleSelector.get("matchLabels"),
tooltip_data=clusterRoleSelector
)
edges.add_rules_resource_names()
ClusterRole/rbac.authorization.k8s.io/v1beta1: ClusterRole/rbac.authorization.k8s.io/v1
ClusterRoleBinding/rbac.authorization.k8s.io/v1:
scope: Cluster
diagram_node_classname: diagrams.k8s.rbac.CRB
edges: |
edges.add_role("roleRef")
edges.add_subjects()
ClusterRoleBinding/rbac.authorization.k8s.io/v1beta1: ClusterRoleBinding/rbac.authorization.k8s.io/v1
ConfigMap/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.podconfig.CM
# no edges
CronJob/batch/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.compute.Cronjob
edges: |
edges.add_owned_resources()
edges.add_service_account("spec.jobTemplate.spec.template.spec")
edges.add_all_volume_resources("spec.jobTemplate.spec.template.spec.volumes")
edges.add_containers_env_value_from_and_env_from("spec.jobTemplate.spec.template.spec.containers")
edges.add_containers_env_value_from_and_env_from("spec.jobTemplate.spec.template.spec.initContainers")
edges.add_containers_env_value_from_and_env_from("spec.jobTemplate.spec.template.spec.ephemeralContainers")
edges.add_wait_for_services("spec.jobTemplate.spec.template.spec.initContainers")
edges.add_networks("spec.jobTemplate.spec.template.metadata.annotations")
edges.add_priority_class("spec.jobTemplate.spec.template.spec.priorityClassName")
edges.add_edge_to(
"spec.jobTemplate.spec.template.spec.runtimeClassName",
".",
None,
"RuntimeClass",
"node.k8s.io/v1",
"REFERENCE"
)
CronJob/batch/v1beta1: CronJob/batch/v1
CustomResourceDefinition/apiextensions.k8s.io/v1:
scope: Cluster
diagram_node_classname: diagrams.k8s.others.CRD
# no edges
CustomResourceDefinition/apiextensions.k8s.io/v1beta1: CustomResourceDefinition/apiextensions.k8s.io/v1
CSIDriver/storage.k8s.io/v1:
scope: Cluster
custom_icon: $KD/icons/csidriver.png
# no edges
CSIDriver/storage.k8s.io/v1beta1: CSIDriver/storage.k8s.io/v1
CSINode/storage.k8s.io/v1:
scope: Cluster
custom_icon: $KD/icons/csinode.png
edges: |
for idx, driver in enumerate(query_path(resource, "spec.drivers", [])):
edges.add_edge_to(
f"spec.drivers[{idx}]",
driver['name'],
None,
"CSIDriver",
"storage.k8s.io/v1",
"REFERENCE",
data=driver
)
CSIStorageCapacity/storage.k8s.io/v1:
scope: Namescaped
custom_icon: $KD/icons/csisc.png
edges: |
edges.add_edge_to(
"storageClassName",
".",
None,
"StorageClass",
"storage.k8s.io/v1",
"REFERENCE"
)
DaemonSet/apps/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.compute.DS
edges: |
edges.add_owned_resources()
edges.add_service_account("spec.template.spec")
edges.add_all_volume_resources("spec.template.spec.volumes")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.containers")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.initContainers")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.ephemeralContainers")
edges.add_wait_for_services("spec.template.spec.initContainers")
edges.add_networks("spec.template.metadata.annotations")
edges.add_priority_class("spec.template.spec.priorityClassName")
edges.add_edge_to(
"spec.template.spec.runtimeClassName",
".",
None,
"RuntimeClass",
"node.k8s.io/v1",
"REFERENCE"
)
DaemonSet/apps/v1beta2: DaemonSet/apps/v1
DaemonSet/extensions/v1beta1: DaemonSet/apps/v1
Deployment/apps/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.compute.Deploy
edges: |
edges.add_owned_resources()
edges.add_service_account("spec.template.spec")
edges.add_all_volume_resources("spec.template.spec.volumes")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.containers")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.initContainers")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.ephemeralContainers")
edges.add_wait_for_services("spec.template.spec.initContainers")
edges.add_networks("spec.template.metadata.annotations")
edges.add_priority_class("spec.template.spec.priorityClassName")
edges.add_edge_to(
"spec.template.spec.runtimeClassName",
".",
None,
"RuntimeClass",
"node.k8s.io/v1",
"REFERENCE"
)
Deployment/extensions/v1beta1: Deployment/apps/v1
Deployment/apps/v1beta1: Deployment/apps/v1
Deployment/apps/v1beta2: Deployment/apps/v1
Endpoints/v1:
scope: Namespaced
plural: endpoints
diagram_node_classname: diagrams.k8s.network.Endpoint
edges: |
for sidx, subset in enumerate(resource.get("subsets", [])):
for aidx, address in enumerate(subset.get("addresses", [])):
if "targetRef" in address:
target = address["targetRef"]
edges.add_edge_to(
f"subsets[{sidx}].addresses[{aidx}].targetRef",
target["name"],
target.get("namespace"),
target["kind"],
"v1",
"REFERENCE",
data=target
)
EndpointSlice/discovery.k8s.io/v1:
scope: Namespaced
custom_icon: $KD/icons/eps.png
edges: |
for idx, endpoint in enumerate(resource.get("endpoints", [])):
if "targetRef" in endpoint:
target = endpoint["targetRef"]
edges.add_edge_to(
f"endpoints[{idx}].targetRef",
target["name"],
target["namespace"],
target["kind"],
"v1",
"REFERENCE",
data=target
)
Group/rbac.authorization.k8s.io/v1:
scope: Cluster
diagram_node_classname: diagrams.k8s.rbac.Group
# no edges
HorizontalPodAutoscaler/autoscaling/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.clusterconfig.HPA
edges: |
edges.add_resource("spec.scaleTargetRef")
HorizontalPodAutoscaler/autoscaling/v2:
scope: Namespaced
diagram_node_classname: diagrams.k8s.clusterconfig.HPA
edges: |
edges.add_resource("spec.scaleTargetRef")
HorizontalPodAutoscaler/autoscaling/v2beta1: HorizontalPodAutoscaler/autoscaling/v2
HorizontalPodAutoscaler/autoscaling/v2beta2: HorizontalPodAutoscaler/autoscaling/v2
Ingress/networking.k8s.io/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.network.Ing
edges: |
edges.add_service("spec.defaultBackend.service.name")
for ridx, rule in enumerate(query_path(resource, "spec.rules", [])):
for pidx, path in enumerate(query_path(rule, "http.paths", [])):
edges.add_service(f"spec.rules[{ridx}].http.paths[{pidx}].backend.service.name", name=query_path(path, "backend.service.name"))
edges.add_edge_to(
"spec.ingressClassName",
".",
None,
"IngressClass",
"networking.k8s.io/v1",
"REFERENCE"
)
for idx, tls in enumerate(query_path(resource, "spec.tls", [])):
edges.add_edge_to(
f"spec.tls[{idx}]",
tls.get("secretName"),
get_namespace(resource),
"Secret",
"v1",
"REFERENCE"
)
Ingress/networking.k8s.io/v1beta1: Ingress/networking.k8s.io/v1
Ingress/extensions/v1beta1: Ingress/networking.k8s.io/v1
IngressClass/networking.k8s.io/v1:
scope: Cluster
custom_icon: $KD/icons/ic.png
edges: |
# TODO: Following works well with ingress-nginx but was not
# been tested with any other ingress implementations.
edges.add_all_resources_matching_labels("Pod", "metadata.labels",
edge_kind="CONTROLLED_BY")
IngressClass/networking.k8s.io/v1beta1: IngressClass/networking.k8s.io/v1
Job/batch/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.compute.Job
edges: |
edges.add_owned_resources()
edges.add_service_account("spec.template.spec")
edges.add_all_volume_resources("spec.template.spec.volumes")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.containers")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.initContainers")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.ephemeralContainers")
edges.add_wait_for_services("spec.template.spec.initContainers")
edges.add_networks("spec.template.metadata.annotations")
edges.add_priority_class("spec.template.spec.priorityClassName")
edges.add_edge_to(
"spec.template.spec.runtimeClassName",
".",
None,
"RuntimeClass",
"node.k8s.io/v1",
"REFERENCE"
)
Job/batch/v1beta1: Job/batch/v1
Lease/coordination.k8s.io/v1:
scope: Namespaced
custom_icon: $KD/icons/lease.png
# no edges
LimitRange/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.clusterconfig.LimitRange
# no edges
MutatingWebhookConfiguration/admissionregistration.k8s.io/v1:
scope: Cluster
custom_icon: $KD/icons/mwc.png
edges: |
edges.add_webhooks()
MutatingWebhookConfiguration/admissionregistration.k8s.io/v1beta1: MutatingWebhookConfiguration/admissionregistration.k8s.io/v1
Namespace/v1:
scope: Cluster
diagram_node_classname: diagrams.k8s.group.NS
# no edges
NetworkAttachmentDefinition/k8s.cni.cncf.io/v1:
scope: Namespaced
diagram_node_classname: diagrams.azure.network.NetworkInterfaces
# no edges
NetworkPolicy/networking.k8s.io/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.network.NetworkPolicy
edges: |
edges.add_all_workload_resources(
"spec.podSelector.matchLabels",
default_selector={},
edge_kind="SELECTOR-UP"
)
edges.add_ingress_and_egress_rules()
Node/v1:
scope: Cluster
diagram_node_classname: diagrams.k8s.infra.Node
edges: |
edges.add_owned_resources()
PersistentVolume/v1:
scope: Cluster
diagram_node_classname: diagrams.k8s.storage.PV
edges: |
edges.add_edge_to(
"spec.storageClassName",
".",
None,
"StorageClass",
"storage.k8s.io/v1",
"REFERENCE"
)
PersistentVolumeClaim/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.storage.PVC
edges: |
if query_path(resource, "spec.storageClassName") != "":
edges.add_edge_to(
"spec.storageClassName",
".",
None,
"StorageClass",
"storage.k8s.io/v1",
"REFERENCE"
)
edges.add_edge_to(
"spec.volumeName",
".",
None,
"PersistentVolume",
"v1",
"REFERENCE"
)
PriorityClass/scheduling.k8s.io/v1:
scope: Cluster
custom_icon: $KD/icons/pc.png
# no edges
PriorityClass/scheduling.k8s.io/v1beta1: PriorityClass/scheduling.k8s.io/v1
Pod/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.compute.Pod
edges: |
edges.add_service_account("spec")
edges.add_all_volume_resources("spec.volumes")
edges.add_containers_env_value_from_and_env_from("spec.containers")
edges.add_containers_env_value_from_and_env_from("spec.initContainers")
edges.add_containers_env_value_from_and_env_from("spec.ephemeralContainers")
edges.add_wait_for_services("spec.initContainers")
edges.add_edge_to(
"spec.nodeName",
".",
None,
"Node",
"v1",
"REFERENCE"
)
edges.add_networks("metadata.annotations")
edges.add_priority_class("spec.priorityClassName")
edges.add_edge_to(
"spec.runtimeClassName",
".",
None,
"RuntimeClass",
"node.k8s.io/v1",
"REFERENCE"
)
PodDisruptionBudget/policy/v1:
scope: Namespaced
custom_icon: $KD/icons/pdb.png
edges: |
edges.add_all_workload_resources(
"spec.selector.matchLabels",
edge_kind="SELECTOR-UP"
)
PodDisruptionBudget/policy/v1beta1: PodDisruptionBudget/policy/v1
PodSecurityPolicy/policy/v1:
scope: Namespaced
plural: podsecuritypolicies
diagram_node_classname: diagrams.k8s.others.PSP
# no edges
PodSecurityPolicy/policy/v1beta1: PodSecurityPolicy/policy/v1
PodSecurityPolicy/extensions/v1beta1: PodSecurityPolicy/policy/v1
PodTemplate/v1:
scope: Namespaced
custom_icon: $KD/icons/podtemplate.png
edges: |
edges.add_service_account("template.spec")
edges.add_all_volume_resources("template.spec.volumes")
edges.add_containers_env_value_from_and_env_from("template.spec.containers")
edges.add_containers_env_value_from_and_env_from("template.spec.initContainers")
edges.add_containers_env_value_from_and_env_from("template.spec.ephemeralContainers")
edges.add_wait_for_services("template.spec.initContainers")
edges.add_edge_to(
"template.spec.nodeName",
".",
None,
"Node",
"v1",
"REFERENCE"
)
edges.add_networks("template.metadata.annotations")
edges.add_priority_class("template.spec.priorityClassName")
edges.add_edge_to(
"template.spec.runtimeClassName",
".",
None,
"RuntimeClass",
"node.k8s.io/v1",
"REFERENCE"
)
ReplicaSet/apps/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.compute.RS
edges: |
edges.add_owned_resources()
edges.add_service_account("spec.template.spec")
edges.add_all_volume_resources("spec.template.spec.volumes")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.containers")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.initContainers")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.ephemeralContainers")
edges.add_wait_for_services("spec.template.spec.initContainers")
edges.add_networks("spec.template.metadata.annotations")
edges.add_priority_class("spec.template.spec.priorityClassName")
edges.add_edge_to(
"spec.template.spec.runtimeClassName",
".",
None,
"RuntimeClass",
"node.k8s.io/v1",
"REFERENCE"
)
ReplicationController/v1:
scope: Namespaced
custom_icon: $KD/icons/rc.png
edges: |
edges.add_owned_resources()
edges.add_service_account("spec.template.spec")
edges.add_all_volume_resources("spec.template.spec.volumes")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.containers")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.initContainers")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.ephemeralContainers")
edges.add_wait_for_services("spec.template.spec.initContainers")
edges.add_networks("spec.template.metadata.annotations")
edges.add_priority_class("spec.template.spec.priorityClassName")
edges.add_edge_to(
"spec.template.spec.runtimeClassName",
".",
None,
"RuntimeClass",
"node.k8s.io/v1",
"REFERENCE"
)
ResourceQuota/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.clusterconfig.Quota
# no edges
Role/rbac.authorization.k8s.io/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.rbac.Role
nodes: |
create_node_for_role_rules_resource_names(resource, nodes)
edges: |
edges.add_rules_resource_names()
Role/rbac.authorization.k8s.io/v1beta1: Role/rbac.authorization.k8s.io/v1
RoleBinding/rbac.authorization.k8s.io/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.rbac.RB
edges: |
edges.add_role("roleRef")
edges.add_subjects()
RoleBinding/rbac.authorization.k8s.io/v1beta1: RoleBinding/rbac.authorization.k8s.io/v1
RuntimeClass/node.k8s.io/v1:
scope: Cluster
custom_icon: $KD/icons/runtimeclass.png
Secret/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.podconfig.Secret
# no edges
Service/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.network.SVC
edges: |
edges.add_edges_for_service()
ServiceAccount/v1:
scope: Namespaced
diagram_node_classname: diagrams.k8s.rbac.SA
# no edges
StatefulSet/apps/v1:
scoped: Namespaced
diagram_node_classname: diagrams.k8s.compute.STS
nodes: |
namespace = resource["metadata"].get("namespace")
for vct in query_path(resource, "spec.volumeClaimTemplates", []):
pvc = {
"kind": "PersistentVolumeClaim",
"apiVersion": "v1",
**vct
}
pvc["metadata"]["name"] = f'{pvc["metadata"]["name"]}-{resource["metadata"]["name"]}'
if namespace is not None:
pvc["metadata"]["namespace"] = namespace
pvc["metadata"]["labels"] = {
**query_path(resource, "metadata.labels", {}),
**query_path(pvc, "metadata.labels", {})
}
nodes.append(pvc)
edges: |
edges.add_owned_resources()
edges.add_service_account("spec.template.spec")
edges.add_all_volume_resources("spec.template.spec.volumes")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.containers")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.initContainers")
edges.add_containers_env_value_from_and_env_from("spec.template.spec.ephemeralContainers")
edges.add_wait_for_services("spec.template.spec.initContainers")
edges.add_networks("spec.template.metadata.annotations")
edges.add_priority_class("spec.template.spec.priorityClassName")
edges.add_edge_to(
"spec.template.spec.runtimeClassName",
".",
None,
"RuntimeClass",
"node.k8s.io/v1",
"REFERENCE"
)
edges.add_volume_claim_templates("spec.volumeClaimTemplates")
edges.add_service("spec.serviceName")
StatefulSet/apps/v1beta1: StatefulSet/apps/v1
StatefulSet/apps/v1beta2: StatefulSet/apps/v1
StorageClass/storage.k8s.io/v1:
scope: Cluster
diagram_node_classname: diagrams.k8s.storage.SC
edges: |
edges.add_edge_to(
"provisioner",
".",
None,
"CSIDriver",
"storage.k8s.io/v1",
"REFERENCE"
)
StorageClass/storage.k8s.io/v1beta1: StorageClass/storage.k8s.io/v1
User/rbac.authorization.k8s.io/v1:
scope: Cluster
diagram_node_classname: diagrams.k8s.rbac.User
# no edges
ValidatingWebhookConfiguration/admissionregistration.k8s.io/v1:
scope: Cluster
custom_icon: $KD/icons/vwc.png
edges: |
edges.add_webhooks()
ValidatingWebhookConfiguration/admissionregistration.k8s.io/v1beta1: ValidatingWebhookConfiguration/admissionregistration.k8s.io/v1
VerticalPodAutoscaler/autoscaling.k8s.io/v1:
scoped: Namespaced
custom_icon: $KD/icons/vpa.png
edges: |
edges.add_resource("spec.targetRef")
VolumeAttachment/storage.k8s.io/v1:
scope: Cluster
diagram_node_classname: diagrams.k8s.storage.Volume
edges: |
edges.add_edge_to(
"spec.nodeName",
".",
None,
"Node",
"v1",
"REFERENCE"
)
cluster-resources:
# default namespace
- default/default/ServiceAccount/v1
- kube-root-ca.crt/default/ConfigMap/v1
- kubernetes/default/Service/v1
# kube-system namespace
- extension-apiserver-authentication-reader/kube-system/Role/rbac.authorization.k8s.io/v1
- horizontal-pod-autoscaler/kube-system/ServiceAccount/v1
# cluster scope
- admin/ClusterRole/rbac.authorization.k8s.io/v1
- cluster-admin/ClusterRole/rbac.authorization.k8s.io/v1
- edit/ClusterRole/rbac.authorization.k8s.io/v1
- generic-garbage-collector/kube-system/ServiceAccount/v1
- standard/StorageClass/storage.k8s.io/v1
- system:anonymous/User/rbac.authorization.k8s.io/v1
- system:auth-delegator/ClusterRole/rbac.authorization.k8s.io/v1
- system:authenticated/Group/rbac.authorization.k8s.io/v1
- system:coredns/ClusterRole/rbac.authorization.k8s.io/v1
- system:discovery/ClusterRole/rbac.authorization.k8s.io/v1
- system:node-proxier/ClusterRole/rbac.authorization.k8s.io/v1
- system:nodes/Group/rbac.authorization.k8s.io/v1
- system:unauthenticated/Group/rbac.authorization.k8s.io/v1
- system:persistent-volume-provisioner/ClusterRole/rbac.authorization.k8s.io/v1
- system:service-account-issuer-discovery/ClusterRole/rbac.authorization.k8s.io/v1
- system:serviceaccounts/Group/rbac.authorization.k8s.io/v1
- system:volume-scheduler/ClusterRole/rbac.authorization.k8s.io/v1
- system-cluster-critical/PriorityClass/scheduling.k8s.io/v1
- system-node-critical/PriorityClass/scheduling.k8s.io/v1
- view/ClusterRole/rbac.authorization.k8s.io/v1

View File

@@ -0,0 +1,110 @@
#!/bin/bash
# kubectl diagrams: A kubectl plugin to generate a diagram of Kubernetes resources
# using kube-diagrams from the output of 'kubectl get <resources> -o yaml'
# Version
VERSION="0.1.0"
# Check if kube-diagrams is installed
if ! command -v kube-diagrams &>/dev/null; then
echo "Error: kube-diagrams is not installed. Please install it first."
exit 1
fi
# Check if kubectl is installed
if ! command -v kubectl &>/dev/null; then
echo "Error: kubectl is not installed. Please install it first."
exit 1
fi
# Display help message
show_help() {
echo "Usage: kubectl diagrams [OPTIONS] <resource1,resource2,...>"
echo ""
echo "A kubectl plugin to generate diagrams of Kubernetes resources using kube-diagrams."
echo ""
echo "Options:"
echo " -n, --namespace <namespace> Specify the namespace to query resources from"
echo " -o, --output <file> Specify the output file for the diagram"
echo " -f, --format <format> Specify the output format (e.g., png, svg)"
echo " --embed-all-icons Embed all icons into svg or dot_json output diagrams"
echo " -c, --config <file> Specify the custom kube-diagrams configuration file"
echo " --without-namespace Exclude namespace from the diagram"
echo " --version Display the version number"
echo " --help Display this help message"
echo ""
echo "Examples:"
echo " kubectl diagrams pod,service -n my-namespace -o diagram.png"
echo " kubectl diagrams deployment --without-namespace -f svg"
echo " kubectl diagrams --version"
exit 0
}
# Initialize variables
KUBE_DIAGRAMS_ARGS=("-") # Default to stdin indicator
KUBECTL_ARGS=()
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--version)
echo "kubectl diagrams version $VERSION"
exit
;;
--help)
show_help
;;
-n | --namespace)
if [[ -n "$2" ]]; then
KUBECTL_ARGS+=("-n" "$2")
shift 2
else
echo "Error: --namespace requires a value"
exit 64
fi
;;
-o | --output | -f | --format | -c | --config | --without-namespace)
KUBE_DIAGRAMS_ARGS+=("$1")
if [[ "$1" == "-o" || "$1" == "--output" || "$1" == "-f" || "$1" == "--format" || "$1" == "-c" || "$1" == "--config" ]]; then
if [[ -n "$2" ]]; then
KUBE_DIAGRAMS_ARGS+=("$2")
shift 2
else
echo "Error: $1 requires a value"
exit 64
fi
else
shift
fi
;;
--embed-all-icons)
KUBE_DIAGRAMS_ARGS+=("$1")
shift
;;
*)
KUBECTL_ARGS+=("$1")
shift
;;
esac
done
# Check if any resources were specified
if [[ ${#KUBECTL_ARGS[@]} -eq 0 ]]; then
echo "Error: At least one resource kind must be specified (e.g., pod, service, deployment)"
exit 64
fi
# Add default output format for kubectl
KUBECTL_ARGS+=("-o" "yaml")
# Execute kubectl and pipe to kube-diagrams with arguments
kubectl get "${KUBECTL_ARGS[@]}" | kube-diagrams "${KUBE_DIAGRAMS_ARGS[@]}"
EXIT_CODE=$?
if [[ $EXIT_CODE -eq 0 ]]; then
echo "Diagram generated successfully"
else
echo "Error: Failed to generate diagram"
exit 1
fi

View File

@@ -0,0 +1,8 @@
#!/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from nodeenv import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -0,0 +1,8 @@
#!/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from charset_normalizer.cli import cli_detect
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(cli_detect())

8
webapp/backend/venv/bin/pip Executable file
View File

@@ -0,0 +1,8 @@
#!/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -0,0 +1,8 @@
#!/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from piptools.scripts.compile import cli
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(cli())

View File

@@ -0,0 +1,8 @@
#!/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from piptools.scripts.sync import cli
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(cli())

8
webapp/backend/venv/bin/pip3 Executable file
View File

@@ -0,0 +1,8 @@
#!/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -0,0 +1,8 @@
#!/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -0,0 +1,8 @@
#!/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pre_commit.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -0,0 +1,8 @@
#!/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from build.__main__ import entrypoint
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(entrypoint())

View File

@@ -0,0 +1 @@
python3

View File

@@ -0,0 +1 @@
/usr/bin/python3

View File

@@ -0,0 +1 @@
python3

View File

@@ -0,0 +1,8 @@
#!/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from virtualenv.__main__ import run_with_catch
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(run_with_catch())

8
webapp/backend/venv/bin/wheel Executable file
View File

@@ -0,0 +1,8 @@
#!/home/spirals/Documents/Workspace/Inria/kubediagramswebui/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from wheel._commands import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -0,0 +1,28 @@
Copyright 2010 Pallets
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,92 @@
Metadata-Version: 2.1
Name: MarkupSafe
Version: 3.0.2
Summary: Safely add untrusted strings to HTML/XML markup.
Maintainer-email: Pallets <contact@palletsprojects.com>
License: Copyright 2010 Pallets
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Project-URL: Donate, https://palletsprojects.com/donate
Project-URL: Documentation, https://markupsafe.palletsprojects.com/
Project-URL: Changes, https://markupsafe.palletsprojects.com/changes/
Project-URL: Source, https://github.com/pallets/markupsafe/
Project-URL: Chat, https://discord.gg/pallets
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Text Processing :: Markup :: HTML
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE.txt
# MarkupSafe
MarkupSafe implements a text object that escapes characters so it is
safe to use in HTML and XML. Characters that have special meanings are
replaced so that they display as the actual characters. This mitigates
injection attacks, meaning untrusted user input can safely be displayed
on a page.
## Examples
```pycon
>>> from markupsafe import Markup, escape
>>> # escape replaces special characters and wraps in Markup
>>> escape("<script>alert(document.cookie);</script>")
Markup('&lt;script&gt;alert(document.cookie);&lt;/script&gt;')
>>> # wrap in Markup to mark text "safe" and prevent escaping
>>> Markup("<strong>Hello</strong>")
Markup('<strong>hello</strong>')
>>> escape(Markup("<strong>Hello</strong>"))
Markup('<strong>hello</strong>')
>>> # Markup is a str subclass
>>> # methods and operators escape their arguments
>>> template = Markup("Hello <em>{name}</em>")
>>> template.format(name='"World"')
Markup('Hello <em>&#34;World&#34;</em>')
```
## Donate
The Pallets organization develops and supports MarkupSafe and other
popular packages. In order to grow the community of contributors and
users, and allow the maintainers to devote more time to the projects,
[please donate today][].
[please donate today]: https://palletsprojects.com/donate

View File

@@ -0,0 +1,15 @@
MarkupSafe-3.0.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
MarkupSafe-3.0.2.dist-info/LICENSE.txt,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475
MarkupSafe-3.0.2.dist-info/METADATA,sha256=aAwbZhSmXdfFuMM-rEHpeiHRkBOGESyVLJIuwzHP-nw,3975
MarkupSafe-3.0.2.dist-info/RECORD,,
MarkupSafe-3.0.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
MarkupSafe-3.0.2.dist-info/WHEEL,sha256=OVgtqZzfzIXXtylXP90gxCZ6CKBCwKYyHM8PpMEjN1M,151
MarkupSafe-3.0.2.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11
markupsafe/__init__.py,sha256=sr-U6_27DfaSrj5jnHYxWN-pvhM27sjlDplMDPZKm7k,13214
markupsafe/__pycache__/__init__.cpython-312.pyc,,
markupsafe/__pycache__/_native.cpython-312.pyc,,
markupsafe/_native.py,sha256=hSLs8Jmz5aqayuengJJ3kdT5PwNpBWpKrmQSdipndC8,210
markupsafe/_speedups.c,sha256=O7XulmTo-epI6n2FtMVOrJXl8EAaIwD2iNYmBI5SEoQ,4149
markupsafe/_speedups.cpython-312-x86_64-linux-gnu.so,sha256=t1DBZlpsjFA30BOOvXfXfT1wvO_4cS16VbHz1-49q5U,43432
markupsafe/_speedups.pyi,sha256=ENd1bYe7gbBUf2ywyYWOGUpnXOHNJ-cgTNqetlW8h5k,41
markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0

View File

@@ -0,0 +1,6 @@
Wheel-Version: 1.0
Generator: setuptools (75.2.0)
Root-Is-Purelib: false
Tag: cp312-cp312-manylinux_2_17_x86_64
Tag: cp312-cp312-manylinux2014_x86_64

Some files were not shown because too many files have changed in this diff Show More