Initialisation depot

This commit is contained in:
Serge NOEL
2026-02-10 12:12:11 +01:00
commit c3176e8d79
818 changed files with 52573 additions and 0 deletions

View File

@@ -0,0 +1,164 @@
# Drone CI Secrets Configuration
This document explains how to configure secrets in Drone CI for the auth-service pipeline.
## Required Secrets
Configure these secrets in your Drone CI interface at `https://drone.aipice.local`:
### Docker Registry Secrets
```bash
# Docker Hub credentials for pushing images
docker_username: your-docker-username
docker_password: your-docker-password-or-token
```
### Git Secrets (Optional)
```bash
# For creating git tags (if using private repos)
git_username: your-git-username
git_token: your-git-personal-access-token
```
### Notification Secrets (Optional)
```bash
# Webhook URL for build notifications (Slack, Discord, etc.)
webhook_url: https://hooks.slack.com/services/YOUR/WEBHOOK/URL
# Drone API token for deployment notifications
drone_token: your-drone-api-token
```
## Setting Up Secrets in Drone
### Via Drone UI
1. Navigate to `https://drone.aipice.local`
2. Go to your repository settings
3. Click on "Secrets" tab
4. Add each secret with the name and value
### Via Drone CLI
```bash
# Install Drone CLI
curl -L https://github.com/harness/drone-cli/releases/latest/download/drone_linux_amd64.tar.gz | tar zx
sudo install -t /usr/local/bin drone
# Configure Drone CLI
export DRONE_SERVER=https://drone.aipice.local
export DRONE_TOKEN=your-drone-token
# Add secrets
drone secret add --repository your-org/auth-service --name docker_username --data your-docker-username
drone secret add --repository your-org/auth-service --name docker_password --data your-docker-password
```
### Via API
```bash
# Add secret via REST API
curl -X POST https://drone.aipice.local/api/repos/your-org/auth-service/secrets \
-H "Authorization: Bearer your-drone-token" \
-H "Content-Type: application/json" \
-d '{
"name": "docker_username",
"data": "your-docker-username"
}' --insecure
```
## Verifying Configuration
### Test Docker Credentials
```bash
# Test Docker login with your credentials
echo "your-docker-password" | docker login -u your-docker-username --password-stdin
```
### Test Drone Connection
```bash
# Test Drone API access
curl -H "Authorization: Bearer your-drone-token" \
https://drone.aipice.local/api/user \
--insecure
```
## Build Trigger
Once secrets are configured, the pipeline will automatically:
1. **On push to main/master:**
- Build Docker image: `hexah/auth-service:1.0.X` (where X is build number)
- Push to Docker registry
- Create Git tag: `v1.0.X`
- Send notifications (if configured)
2. **On push to other branches:**
- Run tests and validation
- Test Docker build (without pushing)
## Version Pattern
The pipeline uses this versioning scheme:
```
Base Version: 1.0 (defined in version.conf)
Build Number: Drone's automatic build counter
Final Version: 1.0.{BUILD_NUMBER}
Examples:
- First build: 1.0.1
- Second build: 1.0.2
- etc.
```
## Customizing Versions
To change the base version (e.g., for major releases):
1. Edit `version.conf`:
```
BASE_VERSION=2.0
```
2. Next build will create: `2.0.1`, `2.0.2`, etc.
## Troubleshooting
### Build Fails on Docker Push
Check that:
- Docker credentials are correct
- Repository `hexah/auth-service` exists
- Account has push permissions
### SSL Certificate Issues
The pipeline includes `skip_verify: true` for self-signed certificates, but you can also:
```bash
# Add Drone server certificate to trusted store
openssl s_client -connect drone.aipice.local:443 -servername drone.aipice.local < /dev/null 2>/dev/null | openssl x509 -outform PEM > drone.crt
sudo cp drone.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
```
### Git Tag Creation Fails
Ensure the Drone service account has push permissions to the repository.
## Example Build Output
Successful build will show:
```
✓ version: Building version 1.0.15
✓ docker-build: Successfully built hexah/auth-service:1.0.15
✓ git-tag: Created tag v1.0.15
✓ deploy-notification: Notified deployment system
```

View File

@@ -0,0 +1,171 @@
# External Buildah Build System - Updated Documentation
## 🎯 Overview
Updated external build system with dynamic pod discovery and concurrent build protection.
## ✨ **New Features**
### 🔍 **Dynamic Pod Discovery**
- Automatically finds running Buildah pods using labels
- No more hardcoded pod names
- Resilient to pod restarts and recreations
### 🔒 **Concurrent Build Protection**
- Lock file mechanism prevents simultaneous builds
- Automatic cleanup of stale locks (older than 10 minutes)
- Timeout protection (5-minute maximum wait)
- Guaranteed lock release even on build failure
### 🛠️ **Enhanced Management**
- Updated management script with dynamic pod discovery
- Lock management commands
- Better error handling and status reporting
## 📋 **How It Works**
### **Dynamic Pod Discovery**
```bash
BUILDAH_POD=$(kubectl get pods -n apps--droneio--prd -l app=buildah-external --field-selector=status.phase=Running -o jsonpath='{.items[0].metadata.name}')
```
### **Locking Mechanism**
1. **Acquire Lock**: Creates `/workspace/locks/build-${DRONE_BUILD_NUMBER}.lock`
2. **Wait for Lock**: Up to 5 minutes timeout with 5-second intervals
3. **Auto-cleanup**: Removes locks older than 10 minutes
4. **Guaranteed Release**: Cleanup step runs on success OR failure
### **Build Process**
1. Find current Buildah pod dynamically
2. Acquire build lock with timeout
3. Transfer source code
4. Execute build in isolated workspace
5. Retrieve results
6. Clean up workspace and release lock
## 🚀 **Usage**
### **Deploy the System**
```bash
./deploy-external-buildah.sh
```
### **Use Production Configuration**
```bash
cp .drone.yml.external-buildah-production .drone.yml
# OR use the current updated version
git add .drone.yml
git commit -m "Implement dynamic external Buildah build"
git push
```
### **Management Commands**
```bash
# Complete status overview
./manage-external-buildah.sh status
# Lock management
./manage-external-buildah.sh locks list # List current locks
./manage-external-buildah.sh locks clean # Remove old locks
./manage-external-buildah.sh locks clear # Remove ALL locks
# Test functionality
./manage-external-buildah.sh test
# Clean old builds
./manage-external-buildah.sh clean
```
## 🔧 **Configuration Files**
### **Updated Files**
-`.drone.yml` - Updated with dynamic discovery and locking
-`manage-external-buildah.sh` - Enhanced management script
-`buildah-external-deployment.yaml` - External Buildah service
-`buildah-rbac.yaml` - RBAC configuration
### **Key Configuration Elements**
#### **Pod Discovery**
```yaml
- BUILDAH_POD=$(kubectl get pods -n apps--droneio--prd -l app=buildah-external --field-selector=status.phase=Running -o jsonpath='{.items[0].metadata.name}')
```
#### **Lock Management**
```yaml
- LOCK_FILE="/workspace/locks/build-${DRONE_BUILD_NUMBER}.lock"
- timeout=300 # 5 minutes maximum wait
```
#### **Cleanup Step**
```yaml
- name: cleanup-build-lock
when:
status:
- success
- failure
```
## 📊 **Benefits**
### **Reliability**
- ✅ No hardcoded pod names
- ✅ Automatic pod discovery
- ✅ Resilient to restarts
### **Concurrency**
- ✅ Prevents build conflicts
- ✅ Automatic lock cleanup
- ✅ Timeout protection
### **Maintenance**
- ✅ Self-managing system
- ✅ Comprehensive status reporting
- ✅ Easy troubleshooting
## 🎯 **Next Steps**
1. **Test the Updated System**:
```bash
./manage-external-buildah.sh status
```
2. **Commit the Configuration**:
```bash
git add .drone.yml
git commit -m "Add dynamic pod discovery and build locking"
git push
```
3. **Monitor First Build**:
- Watch Drone CI interface for build progress
- Check locks: `./manage-external-buildah.sh locks list`
- Verify cleanup: `./manage-external-buildah.sh status`
## 🔍 **Troubleshooting**
### **No Buildah Pod Found**
```bash
kubectl get pods -n apps--droneio--prd -l app=buildah-external
kubectl apply -f buildah-external-deployment.yaml
```
### **Lock Issues**
```bash
# Clean old locks
./manage-external-buildah.sh locks clean
# Clear all locks (emergency)
./manage-external-buildah.sh locks clear
```
### **Build Failures**
```bash
# Check pod logs
./manage-external-buildah.sh logs
# Check pod details
./manage-external-buildah.sh details
```
The system is now production-ready with robust error handling, dynamic discovery, and concurrent build protection!

View File

@@ -0,0 +1,132 @@
# Git Hosting Service Configuration for Drone CI Webhooks
## For Gitea
Add to your Gitea configuration (`app.ini`):
```ini
[webhook]
# Allow webhooks to internal/private networks
ALLOWED_HOST_LIST = private
# Or specifically allow your Drone server
ALLOWED_HOST_LIST = 192.168.100.214,drone.aipice.local,*.aipice.local
# Skip TLS verification for internal services
SKIP_TLS_VERIFY = true
```
Restart Gitea after configuration changes:
```bash
sudo systemctl restart gitea
# or if using Docker:
docker restart gitea
```
## For GitLab
Add to your GitLab configuration (`gitlab.rb`):
```ruby
# Allow outbound requests to private networks
gitlab_rails['outbound_requests_whitelist'] = [
'192.168.100.0/24',
'10.0.0.0/8',
'172.16.0.0/12'
]
# Or specifically allow your Drone server
gitlab_rails['outbound_requests_whitelist'] = ['192.168.100.214']
# Webhook timeout settings
gitlab_rails['webhook_timeout'] = 30
```
Apply configuration:
```bash
sudo gitlab-ctl reconfigure
```
## For GitHub Enterprise
In the GitHub Enterprise admin settings:
1. Go to **Management Console****Privacy**
2. Under **Private Mode**, configure:
- Allow webhook delivery to private networks: ✅
- Exempt domains: `*.aipice.local`
## Alternative: Use Public Domain
If you can't modify the Git hosting service configuration, make your Drone CI accessible via a public domain:
1. **Setup external access** to Drone CI
2. **Use public domain** like `drone-public.yourdomain.com`
3. **Update webhook URL** in Git repository settings
## Testing Webhook Connectivity
Test if your Git service can reach Drone:
```bash
# From your Git hosting server, test connection:
curl -I https://drone.aipice.local/healthz --insecure
# Expected response:
HTTP/1.1 200 OK
```
## Manual Webhook Configuration
If automatic webhook setup fails, configure manually:
1. **Go to repository settings** in your Git service
2. **Add webhook** with:
- URL: `https://drone.aipice.local/hook?secret=YOUR_SECRET`
- Content Type: `application/json`
- Events: `Push`, `Tag push`, `Pull requests`
- SSL verification: Disabled (for self-signed certs)
## Firewall Configuration
Ensure firewall allows Git service to reach Drone:
```bash
# Allow Git server to reach Drone CI
sudo ufw allow from GIT_SERVER_IP to any port 443
sudo ufw allow from 192.168.100.0/24 to any port 443
```
## Troubleshooting
### Check Git Service Logs
**Gitea:**
```bash
sudo journalctl -u gitea -f
# Look for webhook delivery attempts
```
**GitLab:**
```bash
sudo gitlab-ctl tail gitlab-rails
# Look for outbound request blocks
```
### Check Drone Logs
```bash
# Check if Drone receives webhook calls
kubectl logs -n drone deployment/drone-server | grep webhook
```
### Test Manual Webhook
```bash
# Simulate webhook call from Git service
curl -X POST https://drone.aipice.local/hook?secret=YOUR_SECRET \
-H "Content-Type: application/json" \
-H "X-GitHub-Event: push" \
-d '{"ref":"refs/heads/main"}' \
--insecure
```

View File

@@ -0,0 +1,144 @@
# Graceful Termination Solutions for Buildah Container
## 🎯 **Problem**
`sleep infinity` ignores SIGTERM signals, forcing Kubernetes to wait for SIGKILL timeout (default 30 seconds). This causes:
- ⏳ Slow pod termination
- 💸 Unnecessary resource usage during termination
- 🐌 Slower scaling operations
## ✅ **Solutions Implemented**
### **🥇 Recommended: Signal-Aware Bash Loop**
```bash
command: ["/bin/bash"]
args: ["-c", "trap 'exit 0' TERM; while true; do sleep 30 & wait $!; done"]
```
**Benefits:**
-**Immediate response** to SIGTERM (tested: 2 seconds)
-**Simple implementation** - no external dependencies
-**Compatible** with existing infrastructure
-**Resource efficient** - responsive sleep loops
### **⚙️ Configuration Parameters**
```yaml
terminationGracePeriodSeconds: 5 # Reduced from default 30s
readinessProbe:
exec:
command: ["/bin/bash", "-c", "buildah --version"]
initialDelaySeconds: 5
periodSeconds: 10
```
## 📊 **Performance Comparison**
| Method | Termination Time | Complexity | Resource Usage |
|--------|------------------|------------|----------------|
| `sleep infinity` | 30s (SIGKILL) | Low | High during termination |
| **Signal-aware loop** | **2s** | Low | **Low** |
| Custom entrypoint | 3-5s | Medium | Low |
| Chart override | Variable | High | Low |
## 🔧 **Implementation Options**
### **Option 1: Direct Deployment Update** ⭐
```yaml
command: ["/bin/bash"]
args: ["-c", "trap 'exit 0' TERM; while true; do sleep 30 & wait $!; done"]
terminationGracePeriodSeconds: 5
```
**Use when:** Direct control over deployment YAML
### **Option 2: Chart Override Values**
```yaml
# For Helm chart deployments
buildah-external:
command: ["/bin/bash"]
args: ["-c", "trap 'exit 0' TERM; while true; do sleep 30 & wait $!; done"]
terminationGracePeriodSeconds: 5
```
**Use when:** Deployment managed by Helm charts
### **Option 3: ConfigMap Entrypoint**
```yaml
# More sophisticated signal handling with cleanup
volumeMounts:
- name: entrypoint-script
mountPath: /scripts
volumes:
- name: entrypoint-script
configMap:
name: buildah-entrypoint
```
**Use when:** Need complex termination logic or cleanup
## 🧪 **Validation**
### **Test Graceful Termination**
```bash
pipeline/test-graceful-termination.sh
```
**Validates:**
- ✅ Pod responsiveness during operation
- ✅ Signal handling speed (target: <10s)
- ✅ Clean termination without SIGKILL
- ✅ Proper deployment scaling
### **Test Results**
```
✅ Pod terminated in 2 seconds
🎉 Excellent! Graceful termination completed quickly (≤10s)
📝 Method: Signal-aware bash loop with trap
```
## 🔄 **Integration with Replica Locking**
The signal-aware termination works perfectly with the replica-based locking system:
```bash
# Scale up (acquire lock) - fast startup
kubectl scale deployment buildah-external --replicas=1
kubectl wait --for=condition=ready pod -l app=buildah-external --timeout=60s
# Scale down (release lock) - fast termination
kubectl scale deployment buildah-external --replicas=0
kubectl wait --for=delete pod -l app=buildah-external --timeout=10s # Much faster!
```
## 📋 **Migration Steps**
1. **Update deployment** with signal-aware command
2. **Reduce termination grace period** to 5-10 seconds
3. **Add readiness probe** for build verification
4. **Test termination speed** with validation script
5. **Monitor** build pipeline performance
## 🎯 **Benefits Achieved**
- **🚀 15x faster termination** (30s → 2s)
- **💰 Resource savings** during scaling operations
- **🔧 Better UX** for developers (faster builds)
- **⚡ Responsive scaling** for replica-based locking
- **🛡️ Robust** - handles signals properly
## 🔍 **Monitoring Commands**
```bash
# Check termination grace period
kubectl get pod <pod-name> -o jsonpath='{.spec.terminationGracePeriodSeconds}'
# Monitor termination events
kubectl get events --field-selector involvedObject.name=<pod-name>
# Test signal responsiveness
kubectl exec <pod-name> -- kill -TERM 1
```
This solution provides **optimal performance** while maintaining **simplicity** and **compatibility** with existing infrastructure! 🎉

View File

@@ -0,0 +1,169 @@
# Drone CI Jsonnet Configuration Guide
## ✅ **Jsonnet is Now Enabled!**
Your Drone CI server now supports Jsonnet configurations with the following setup:
### 🔧 **Server Configuration**
The following environment variables have been added to enable Jsonnet:
```yaml
DRONE_JSONNET_ENABLED: "true"
DRONE_STARLARK_ENABLED: "true" # Bonus: Starlark support too
```
### 📁 **File Structure**
```
├── .drone.jsonnet # Main pipeline configuration
├── common.libsonnet # Shared steps and environment
├── build-steps.libsonnet # Build-specific logic
├── .drone.yml.backup # Original YAML (backup)
└── drone-configmap-updated.yaml # Updated server config
```
## 🚀 **How to Use Jsonnet**
### **1. Main Configuration (`.drone.jsonnet`)**
- Entry point for your pipeline
- Imports and combines modules
- Generates final pipeline configuration
### **2. Common Module (`common.libsonnet`)**
- Shared environment variables
- Common steps (clone, test, cleanup)
- Reusable triggers and conditions
### **3. Build Module (`build-steps.libsonnet`)**
- Build-specific logic
- External Buildah integration
- Container build steps
## 🔄 **Workflow**
1. **Edit Jsonnet files** (`.drone.jsonnet`, `*.libsonnet`)
2. **Test locally** (optional): `jsonnet .drone.jsonnet`
3. **Commit and push** - Drone automatically processes Jsonnet
4. **Pipeline runs** using generated configuration
## 🛠️ **Local Development**
### **Generate YAML for testing:**
```bash
# Generate YAML from Jsonnet
jsonnet .drone.jsonnet > .drone.yml.test
# Validate generated YAML
python3 -c "import yaml; yaml.safe_load(open('.drone.yml.test'))"
# Compare with original
diff .drone.yml.backup .drone.yml.test
```
### **Jsonnet Utilities:**
```bash
# Format Jsonnet files
jsonnetfmt -i .drone.jsonnet common.libsonnet build-steps.libsonnet
# Validate syntax
jsonnet .drone.jsonnet > /dev/null && echo "✅ Valid Jsonnet"
```
## 🎯 **Benefits Achieved**
### **Modularity**
- ✅ Separate concerns (common vs build-specific)
- ✅ Reusable components
- ✅ Easier maintenance
### **Flexibility**
- ✅ Variables and functions
- ✅ Conditional logic
- ✅ Dynamic configuration
### **DRY Principle**
- ✅ No code duplication
- ✅ Single source of truth
- ✅ Consistent patterns
## 📋 **Configuration Examples**
### **Creating Environment-Specific Builds:**
```jsonnet
// .drone.jsonnet
local buildSteps = import 'build-steps.libsonnet';
local commonConfig = import 'common.libsonnet';
local environment = std.extVar('environment');
{
kind: "pipeline",
type: "kubernetes",
name: "auth-service-" + environment,
service_account: "drone-runner",
environment: commonConfig.environment + {
BUILD_ENV: environment
},
steps: [
commonConfig.cloneStep,
commonConfig.testStep,
buildSteps.externalBuildahStep + {
commands: [
// Add environment-specific commands
"echo 'Building for: " + environment + "'",
] + buildSteps.externalBuildahStep.commands
}
]
}
```
### **Adding Conditional Steps:**
```jsonnet
// build-steps.libsonnet
{
externalBuildahStep: {
// ... existing configuration
commands: [
// ... existing commands
] + (
if std.extVar('push_to_registry') == 'true' then [
"echo '📤 Pushing to registry...'",
"kubectl exec $BUILDAH_POD -- buildah push auth-service:1.0.${DRONE_BUILD_NUMBER} docker://registry.aipice.local/auth-service:1.0.${DRONE_BUILD_NUMBER}"
] else []
)
}
}
```
## 🔍 **Troubleshooting**
### **Check if Jsonnet is enabled:**
```bash
kubectl get configmap drone -n apps--droneio--prd -o yaml | grep JSONNET
```
### **Verify Drone server restart:**
```bash
kubectl get pods -n apps--droneio--prd | grep droneio
```
### **Test Jsonnet syntax:**
```bash
jsonnet .drone.jsonnet | python3 -c "import sys,yaml; yaml.safe_load(sys.stdin)"
```
### **View generated pipeline in Drone UI:**
- Go to your repository in Drone UI
- The generated YAML will be shown in the build view
## 🎉 **Next Steps**
1. **Create variants**: Development, staging, production configurations
2. **Add functions**: Custom build logic, notification steps
3. **Share modules**: Reuse across multiple repositories
4. **Optimize**: Use Jsonnet's advanced features for complex scenarios
Your Drone CI is now supercharged with Jsonnet! 🚀

View File

@@ -0,0 +1,306 @@
# Multi-Domain Authentication for *.aipice.fr
This guide shows how to use a single authentication service to protect multiple subdomains under `aipice.fr`.
## 🎯 Architecture Overview
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ auth.aipice.fr │ │ arti-api.aipice │ │ *.aipice.fr │
│ │ │ .fr │ │ │
│ Auth Service │───▶│ Protected API │ │ Other Services │
│ (Login Page) │ │ (with auth) │ │ (with auth) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
└────────────────────────┼────────────────────────┘
┌─────────────────┐
│ Active Directory│
│ Validation │
└─────────────────┘
```
## 🚀 Quick Setup for aipice.fr
### 1. Deploy the Authentication Service
```bash
# Run the deployment script
./deploy-aipice.sh
# This will:
# - Create wildcard certificate for *.aipice.fr
# - Deploy auth service at auth.aipice.fr
# - Protect arti-api.aipice.fr with authentication
# - Create reusable ForwardAuth middleware
```
### 2. Access Your Services
- **Authentication**: https://auth.aipice.fr
- **Protected API**: https://arti-api.aipice.fr (requires login)
- **Public endpoints**: https://arti-api.aipice.fr/ and /health (no auth)
## 🔒 How Multi-Domain Protection Works
### Authentication Flow
1. **User visits** `https://arti-api.aipice.fr/users`
2. **Traefik checks** auth via ForwardAuth middleware
3. **No token?** → Redirect to `https://auth.aipice.fr/?return_url=https://arti-api.aipice.fr/users`
4. **User logs in** → JWT token stored in cookie for `.aipice.fr` domain
5. **User redirected** back to `https://arti-api.aipice.fr/users`
6. **Traefik validates** token → Access granted
### Cross-Domain Cookie Sharing
The auth service sets cookies with `domain=.aipice.fr`, making them available to all subdomains:
```python
response.set_cookie(
key="auth_token",
value=token,
domain=".aipice.fr", # Works for all *.aipice.fr
httponly=True,
secure=True,
samesite="lax"
)
```
## 🛡️ Protecting Additional Services
To protect any new subdomain (e.g., `grafana.aipice.fr`), simply add the ForwardAuth middleware:
```yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: grafana-protected
spec:
entryPoints:
- websecure
routes:
- match: Host(`grafana.aipice.fr`)
kind: Rule
services:
- name: grafana
port: 3000
middlewares:
- name: auth-forward
namespace: infrastructure--artifactory--service # Where auth service is deployed
tls:
secretName: wildcard-aipice-fr
```
## 📋 Configuration Examples
### Multiple Protection Levels
You can create different auth requirements for different services:
```yaml
# Public service (no auth)
- match: Host(`public.aipice.fr`)
services:
- name: public-service
port: 80
# Basic auth required
- match: Host(`internal.aipice.fr`)
services:
- name: internal-service
port: 80
middlewares:
- name: auth-forward
# Admin-only access (custom verification)
- match: Host(`admin.aipice.fr`)
services:
- name: admin-service
port: 80
middlewares:
- name: admin-auth-forward # Custom middleware with admin check
```
### Group-Based Access Control
Use Active Directory groups for fine-grained access:
```python
# In your backend service
def require_admin_group(x_auth_groups: str = Header(None)):
groups = x_auth_groups.split(',') if x_auth_groups else []
admin_groups = [
'CN=Domain Admins,CN=Users,DC=aipice,DC=fr',
'CN=IT Team,CN=Groups,DC=aipice,DC=fr'
]
if not any(group in groups for group in admin_groups):
raise HTTPException(status_code=403, detail="Admin access required")
```
## 🔧 Advanced Configuration
### Environment Variables
The auth service supports these domain-specific variables:
```yaml
env:
- name: ALLOWED_DOMAINS
value: "aipice.fr,yourdomain.com" # Multiple domains supported
- name: AUTH_DOMAIN
value: "auth.aipice.fr"
- name: CORS_ORIGINS
value: "https://*.aipice.fr,https://*.yourdomain.com"
```
### Wildcard Certificate
For automatic SSL across all subdomains:
```yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wildcard-aipice-fr
spec:
secretName: wildcard-aipice-fr
issuerRef:
name: letsencrypt
kind: ClusterIssuer
commonName: "*.aipice.fr"
dnsNames:
- "aipice.fr"
- "*.aipice.fr"
```
## 🎨 Customizing the Login Page
Update the login page branding for your domain:
```html
<!-- In templates/login.html -->
<div class="login-header">
<h1>🔐 Aipice Access</h1>
<p>Sign in to access Aipice services</p>
</div>
```
## 📊 Monitoring and Logs
### Check Authentication Status
```bash
# View auth service logs
kubectl logs -n infrastructure--artifactory--service deployment/auth-service
# Check ForwardAuth requests
kubectl logs -n traefik deployment/traefik | grep "auth-forward"
# Test authentication
curl -H "Authorization: Bearer $TOKEN" https://auth.aipice.fr/auth/verify
```
### Common Log Entries
```
INFO: Successfully authenticated user: john.doe accessing arti-api.aipice.fr
INFO: No token found, redirecting to: https://auth.aipice.fr/?return_url=https://grafana.aipice.fr/
WARNING: Access denied for domain: suspicious.domain.com
```
## 🔍 Troubleshooting
### Issue: "Page isn't redirecting properly"
**Cause**: Redirect loop between auth service and protected service.
**Solution**: Ensure auth service domain is excluded from ForwardAuth:
```yaml
routes:
- match: Host(`auth.aipice.fr`)
# No auth-forward middleware here!
services:
- name: auth-service
```
### Issue: "Authentication required" but user is logged in
**Cause**: Cookie domain mismatch or token expiration.
**Solution**: Check cookie domain and token validity:
```bash
# Check token in browser console
localStorage.getItem('auth_token')
# Verify token server-side
curl -H "Authorization: Bearer $TOKEN" https://auth.aipice.fr/auth/verify
```
### Issue: Cross-domain cookie not working
**Cause**: Cookie domain not set correctly.
**Solution**: Ensure cookie domain starts with dot:
```python
domain=".aipice.fr" # ✅ Works for all subdomains
domain="aipice.fr" # ❌ Only works for exact domain
```
## 📈 Scaling Considerations
### High Availability
```yaml
spec:
replicas: 3 # Multiple auth service instances
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
```
### Performance Tuning
```yaml
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "500m"
```
### Caching
Consider adding Redis for token caching in high-traffic scenarios:
```yaml
- name: REDIS_URL
value: "redis://redis-service:6379"
```
## 🎯 Real-World Example
Here's a complete setup for a company using multiple services:
```yaml
# Services protected by auth.aipice.fr:
# - arti-api.aipice.fr (Artifactory API)
# - grafana.aipice.fr (Monitoring)
# - jenkins.aipice.fr (CI/CD)
# - nextcloud.aipice.fr (File sharing)
# - wiki.aipice.fr (Documentation)
# All use the same ForwardAuth middleware
# All share the same authentication cookie
# All redirect to auth.aipice.fr when needed
# All respect Active Directory group memberships
```
This gives you enterprise-grade authentication across your entire `*.aipice.fr` infrastructure with a single, centralized auth service!

View File

@@ -0,0 +1,67 @@
# Pipeline Configuration Files
This folder contains all Drone CI pipeline-related configuration files and scripts.
## 📁 **File Organization**
### **🔧 Jsonnet Configuration**
- `common.libsonnet` - Shared pipeline components (steps, environment, triggers)
- `build-steps.libsonnet` - Build-specific logic (external Buildah integration)
### **🚀 Management Scripts**
- `manage-external-buildah.sh` - External Buildah service management
- `update-buildah-pod.sh` - Auto-update pod references in configurations
- `deploy-external-buildah.sh` - Complete deployment automation
- `convert-to-jsonnet.sh` - Migration helper from YAML to Jsonnet
### **⚙️ Kubernetes Resources**
- `buildah-external-deployment.yaml` - External Buildah service deployment
- `buildah-rbac.yaml` - RBAC for Buildah operations
- `drone-build-rbac.yaml` - RBAC for Drone build steps
- `default-sa-binding.yaml` - Service account permissions
- `drone-configmap-updated.yaml` - Drone server configuration with Jsonnet support
### **📋 Alternative Configurations**
- Various `.drone.yml.*` files - Alternative pipeline configurations for reference
- `.drone.star.example` - Starlark configuration example (not used)
### **📚 Documentation**
- `EXTERNAL-BUILDAH-SYSTEM.md` - External build system documentation
- `JSONNET-GUIDE.md` - Jsonnet usage guide
- Other analysis and guide files
## 🔄 **Usage Workflow**
1. **Edit Configuration**: Modify `common.libsonnet` or `build-steps.libsonnet`
2. **Test Locally**: `cd .. && jsonnet .drone.jsonnet`
3. **Deploy**: Commit and push changes
4. **Manage**: Use scripts in this folder for maintenance
## 🎯 **Key Benefits**
- **🧩 Organized Structure**: All pipeline files in one place
- **🔄 Modular Design**: Separate concerns and reusable components
- **📝 Easy Maintenance**: Clear file organization and documentation
- **🛠️ Management Tools**: Complete set of automation scripts
## 📖 **Quick Start**
```bash
# Test current configuration
cd .. && jsonnet .drone.jsonnet
# Check external Buildah status
./manage-external-buildah.sh status
# Deploy complete system
./deploy-external-buildah.sh
# Update pod references after restarts
./update-buildah-pod.sh
```
## 🔗 **Related Files**
- `../.drone.jsonnet` - Root-level entry point (imports from this folder)
- `../Dockerfile` - Application container definition
- `../requirements.txt` - Application dependencies

View File

@@ -0,0 +1,429 @@
# Authentication Service with Active Directory Integration
This authentication service provides JWT-based authentication with Active Directory integration and Traefik ForwardAuth support for Kubernetes environments.
## Features
- 🔐 **Active Directory Authentication**: Validates credentials against your AD server
- 🎫 **JWT Tokens**: Secure token-based authentication with configurable expiration
- 🍪 **Cookie & Local Storage**: Tokens stored securely in HTTP-only cookies and locally
- 🚀 **Traefik Integration**: ForwardAuth middleware for seamless Kubernetes access control
- 📱 **Responsive UI**: Clean, modern login interface
- 🔒 **Security Headers**: Proper CORS, security headers, and token validation
## Architecture
```
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ User Browser │───▶│ Auth Service │───▶│ Active Directory│
│ │ │ │ │ │
│ 1. Login Form │ │ 2. Validate AD │ │ 3. LDAP Auth │
│ 4. Store Token │◀───│ Create JWT │ │ │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐
│ Protected API │◀───│ Traefik Forward │
│ │ │ Auth Middleware │
│ 5. Access with │ │ 6. Validate JWT │
│ JWT Token │ │ │
└─────────────────┘ └──────────────────┘
```
## Quick Start
### 1. Build and Deploy
```bash
# Build the authentication service
cd auth-service
docker build -t your-registry/auth-service:1.0.0 .
docker push your-registry/auth-service:1.0.0
# Update values in values-example.yaml
cp values-example.yaml values.yaml
# Edit values.yaml with your AD configuration
# Deploy to Kubernetes
kubectl apply -f kubernetes-auth.yaml
```
### 2. Configure Active Directory
Update the `values.yaml` file with your AD configuration:
```yaml
authService:
activeDirectory:
server: "ldap://your-ad-server.yourdomain.com"
baseDN: "DC=yourdomain,DC=com"
userSearchBase: "CN=Users,DC=yourdomain,DC=com"
bindUser: "CN=ServiceAccount,CN=Users,DC=yourdomain,DC=com"
bindPassword: "your-service-account-password"
```
### 3. Configure Traefik ForwardAuth
The service automatically creates a ForwardAuth middleware that:
```yaml
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: auth-forward
spec:
forwardAuth:
address: http://auth-service:8080/auth/verify
authResponseHeaders:
- "X-Auth-User"
- "X-Auth-Email"
- "X-Auth-Groups"
- "X-Auth-Display-Name"
```
### 4. Protect Your Services
Add the ForwardAuth middleware to any IngressRoute:
```yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: protected-service
spec:
routes:
- match: Host(`api.yourdomain.com`)
kind: Rule
services:
- name: your-api-service
port: 8000
middlewares:
- name: auth-forward # This protects the entire service
```
## How It Works
### Authentication Flow
1. **User visits protected resource** → Traefik ForwardAuth redirects to login
2. **User enters AD credentials** → Service validates against Active Directory
3. **JWT token created** → Stored in HTTP-only cookie + localStorage
4. **Subsequent requests** → Traefik validates JWT via ForwardAuth
5. **Access granted** → User headers passed to backend service
### Token Storage
The system uses a dual-storage approach:
- **HTTP-only Cookie**: Secure, automatic transmission, protected from XSS
- **localStorage**: Available to JavaScript for SPA applications
### Security Features
-**LDAP over TLS** support for secure AD communication
-**JWT token expiration** with configurable timeouts
-**HTTP-only cookies** prevent XSS token theft
-**Secure headers** for production deployment
-**CORS protection** with configurable origins
## API Endpoints
### Authentication Endpoints
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/` | GET | Login page (HTML) |
| `/dashboard` | GET | Dashboard page (HTML) |
| `/auth/login` | POST | Authenticate user |
| `/auth/verify` | POST | Verify JWT token (ForwardAuth) |
| `/auth/logout` | GET | Logout user |
| `/auth/user` | GET | Get current user info |
| `/health` | GET | Health check |
### ForwardAuth Integration
When Traefik calls `/auth/verify`, the service:
1. **Checks for token** in Authorization header or cookies
2. **Validates JWT** signature and expiration
3. **Returns user headers** for backend services:
- `X-Auth-User`: Username
- `X-Auth-Email`: User email
- `X-Auth-Groups`: AD group memberships
- `X-Auth-Display-Name`: User's display name
## Configuration
### Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `JWT_SECRET` | Secret key for JWT signing | (required) |
| `TOKEN_EXPIRE_HOURS` | Token expiration in hours | 8 |
| `AD_SERVER` | LDAP server URL | (required) |
| `AD_BASE_DN` | Base DN for AD | (required) |
| `AD_USER_SEARCH_BASE` | User search base | (required) |
| `AD_BIND_USER` | Service account for LDAP | (optional) |
| `AD_BIND_PASSWORD` | Service account password | (optional) |
### Kubernetes Secrets
Create the required secrets:
```bash
kubectl create secret generic auth-secrets \
--from-literal=jwt-secret="your-super-secret-key" \
--from-literal=ad-bind-user="CN=ServiceAccount,CN=Users,DC=yourdomain,DC=com" \
--from-literal=ad-bind-password="your-service-password"
```
## Advanced Usage
### Custom Group-Based Access
The service passes AD group memberships in the `X-Auth-Groups` header. You can use this in your backend services:
```python
# In your FastAPI backend
from fastapi import Header
def check_admin_access(x_auth_groups: str = Header(None)):
groups = x_auth_groups.split(',') if x_auth_groups else []
if 'CN=Admins,CN=Groups,DC=yourdomain,DC=com' not in groups:
raise HTTPException(status_code=403, detail="Admin access required")
```
### Multiple Protection Levels
You can create different ForwardAuth middlewares for different access levels:
```yaml
# Admin-only middleware
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: admin-auth
spec:
forwardAuth:
address: http://auth-service:8080/auth/verify-admin
authResponseHeaders:
- "X-Auth-User"
- "X-Auth-Groups"
```
### Token Refresh
The service automatically handles token refresh. Configure shorter expiration times and implement refresh logic in your frontend:
```javascript
// Check token expiration
const token = localStorage.getItem('auth_token');
const payload = JSON.parse(atob(token.split('.')[1]));
const expiry = new Date(payload.exp * 1000);
if (expiry < new Date()) {
// Redirect to login for refresh
window.location.href = '/auth/login';
}
```
## Monitoring
### Health Checks
The service includes health check endpoints:
```bash
curl http://auth-service:8080/health
```
### Logging
The service logs authentication attempts and failures:
```
INFO: Successfully authenticated user: john.doe
ERROR: Authentication failed for user: invalid.user
ERROR: LDAP connection failed: timeout
```
## Security Considerations
1. **Use HTTPS**: Always deploy with TLS certificates
2. **Secure JWT Secret**: Use a strong, unique JWT secret
3. **Network Security**: Restrict access to AD servers
4. **Token Expiration**: Use reasonable token expiration times
5. **Service Account**: Use a dedicated AD service account with minimal permissions
6. **Audit Logs**: Monitor authentication logs for suspicious activity
## Troubleshooting
### Common Issues
1. **LDAP Connection Failed**
- Check AD server connectivity
- Verify LDAP URL format
- Check firewall rules
2. **Authentication Failed**
- Verify AD credentials
- Check user search base DN
- Confirm user exists in specified OU
3. **ForwardAuth Not Working**
- Verify Traefik middleware configuration
- Check service connectivity
- Review Traefik logs
4. **Token Issues**
- Verify JWT secret consistency
- Check token expiration
- Validate cookie settings
### Debug Mode
Enable debug logging by setting log level:
```yaml
env:
- name: LOG_LEVEL
value: "DEBUG"
```
This will provide detailed authentication flow logs.
# 🔧 Drone Configuration Factorization Options
## 1. Jsonnet Configuration (Recommended)
Drone supports Jsonnet for dynamic configuration generation, which allows you to include files and create reusable components.
## 2. YAML Anchors & References (Limited)
YAML supports anchors and references for basic factorization:
## 3. External Configuration Files (Starlark)
Drone also supports Starlark (Python-like) for advanced configuration:
🎯 Recommended: Convert to Jsonnet
Let me create a script to help you convert your current .drone.yml to the modular Jsonnet approach:
convert-to-jsonnet.sh
```bash
#!/bin/bash
# Convert existing .drone.yml to modular Jsonnet structure
# This script helps migrate from YAML to factorized Jsonnet configuration
echo "🔄 Converting Drone configuration to modular Jsonnet..."
# Generate the final configuration from Jsonnet
echo "📝 Generating .drone.yml from Jsonnet..."
if command -v jsonnet >/dev/null 2>&1; then
jsonnet .drone.jsonnet > .drone.yml.generated
echo "✅ Generated .drone.yml.generated from Jsonnet"
echo ""
echo "📋 To use the new configuration:"
echo "1. Review: cat .drone.yml.generated"
echo "2. Test: python3 -c \"import yaml; yaml.safe_load(open('.drone.yml.generated'))\""
echo "3. Replace: mv .drone.yml.generated .drone.yml"
echo "4. Commit: git add .drone.jsonnet common.libsonnet build-steps.libsonnet .drone.yml"
else
echo "⚠️ jsonnet not installed. Installing..."
# Try to install jsonnet
if command -v apt-get >/dev/null 2>&1; then
sudo apt-get update && sudo apt-get install -y jsonnet
elif command -v apk >/dev/null 2>&1; then
apk add --no-cache jsonnet
elif command -v yum >/dev/null 2>&1; then
sudo yum install -y jsonnet
else
echo "❌ Cannot install jsonnet automatically"
echo "📖 Please install jsonnet manually:"
echo " - Ubuntu/Debian: sudo apt-get install jsonnet"
echo " - Alpine: apk add jsonnet"
echo " - CentOS/RHEL: sudo yum install jsonnet"
echo " - Or download from: https://github.com/google/jsonnet"
exit 1
fi
# Try generating again
if command -v jsonnet >/dev/null 2>&1; then
jsonnet .drone.jsonnet > .drone.yml.generated
echo "✅ Generated .drone.yml.generated from Jsonnet"
else
echo "❌ Failed to install jsonnet"
exit 1
fi
fi
echo ""
echo "🎯 Benefits of Jsonnet configuration:"
echo " ✅ Reusable components (common.libsonnet, build-steps.libsonnet)"
echo " ✅ Variables and functions"
echo " ✅ Conditional logic"
echo " ✅ Better maintainability"
echo " ✅ DRY principle"
echo ""
echo "📚 Files created:"
echo " - .drone.jsonnet (main configuration)"
echo " - common.libsonnet (shared steps and config)"
echo " - build-steps.libsonnet (build-specific logic)"
echo " - .drone.yml.generated (generated YAML)"
# Validate the generated YAML
if [ -f ".drone.yml.generated" ]; then
echo ""
echo "🔍 Validating generated YAML..."
if python3 -c "import yaml; yaml.safe_load(open('.drone.yml.generated'))" 2>/dev/null; then
echo "✅ Generated YAML is valid"
else
echo "❌ Generated YAML has syntax errors"
exit 1
fi
fi
```
# 📋 Summary of Factorization Options
| Method | Pros | Cons | Best For |
| ------ | ---- | ---- | -------- |
| Jsonnet | ✅ Full programming language<br>✅ Variables, functions, imports<br>✅ Conditional logic | ❌ Learning curve<br>❌ Requires jsonnet tool | Complex configurations |
| YAML Anchors | ✅ Native YAML<br>✅ Simple syntax<br>✅ No extra tools | ❌ Limited functionality<br>❌ No conditionals | Simple repetition |
| Starlark | ✅ Python-like syntax<br>✅ Advanced logic<br>✅ Built into Drone | ❌ Drone-specific<br>❌ Less common | Advanced pipelines |
# 🎯 Recommendation for Your Project
For your external Buildah build system, I recommend Jsonnet because:
- **Modularity**: Separate build logic from common steps
- **Reusability**: Common kubectl setup, environment config
- **Maintainability**: Easier to update build steps independently
- **Flexibility**: Can create variants (dev, staging, prod) easily
## 🚀 Quick Start with Jsonnet
```console
# Install jsonnet (if needed)
sudo apt-get install jsonnet
# Convert to modular structure
./convert-to-jsonnet.sh
# Review generated configuration
cat .drone.yml.generated
# Test and deploy
mv .drone.yml.generated .drone.yml
git add .drone.jsonnet common.libsonnet build-steps.libsonnet .drone.yml
git commit -m "Convert to modular Jsonnet configuration"
git push
```
The modular approach will make it much easier to:
- 🔧 Update build steps without touching common logic
- 🎯 Create environment-specific configurations
- 🧪 Test individual components
- 📦 Share configuration across projects

View File

@@ -0,0 +1,152 @@
# Replica-Based Build Locking System
## 🎯 **Concept**
Instead of using lock files, we use Kubernetes deployment **replica scaling** as an atomic locking mechanism:
- **Replicas = 0**: No build running (lock available)
- **Replicas = 1**: Build in progress (lock acquired)
## 🔧 **How It Works**
### **Build Start (Lock Acquisition)**
```bash
# Check if lock is available
CURRENT_REPLICAS=$(kubectl get deployment buildah-external -o jsonpath='{.spec.replicas}')
if [ "$CURRENT_REPLICAS" = "0" ]; then
# Acquire lock by scaling up
kubectl scale deployment buildah-external --replicas=1
kubectl wait --for=condition=ready pod -l app=buildah-external --timeout=120s
else
# Lock unavailable - build already running
exit 1
fi
```
### **Build End (Lock Release)**
```bash
# Always release lock (runs on success OR failure)
kubectl scale deployment buildah-external --replicas=0
kubectl wait --for=delete pod -l app=buildah-external --timeout=60s
```
## ✅ **Benefits**
### **🔒 Atomic Operations**
- **Kubernetes guarantees** atomic scaling operations
- **No race conditions** possible between concurrent builds
- **Built-in conflict resolution** via Kubernetes API
### **🚀 Resource Efficiency**
- **Zero resource usage** when no builds are running
- **Pod only exists** during active builds
- **Automatic cleanup** of compute resources
### **🛡️ Robust Error Handling**
- **Scale-down always runs** (success or failure)
- **No stale locks** - Kubernetes manages lifecycle
- **Self-healing** if pods crash during build
### **📊 Observable State**
- **Easy monitoring**: `kubectl get deployment buildah-external`
- **Clear status**: Replica count = build status
- **No hidden state** in lock files
## 🔄 **Build Pipeline Flow**
```mermaid
graph TD
A[Build Triggered] --> B{Check Replicas}
B -->|replicas=0| C[Scale to 1]
B -->|replicas≠0| D[❌ Build Already Running]
C --> E[Wait for Pod Ready]
E --> F[Execute Build]
F --> G[Scale to 0]
G --> H[✅ Build Complete]
D --> I[❌ Exit with Error]
```
## 📋 **Pipeline Implementation**
### **Build Step**
```jsonnet
{
name: "build-via-external-buildah",
commands: [
// Check current replicas
"CURRENT_REPLICAS=$(kubectl get deployment buildah-external -o jsonpath='{.spec.replicas}')",
// Acquire lock or fail
"if [ \"$CURRENT_REPLICAS\" = \"0\" ]; then",
" kubectl scale deployment buildah-external --replicas=1",
" kubectl wait --for=condition=ready pod -l app=buildah-external --timeout=120s",
"else",
" echo \"Build already running!\"; exit 1",
"fi",
// ... build commands ...
]
}
```
### **Cleanup Step**
```jsonnet
{
name: "scale-down-buildah",
commands: [
"kubectl scale deployment buildah-external --replicas=0",
"kubectl wait --for=delete pod -l app=buildah-external --timeout=60s"
],
when: {
status: ["success", "failure"] // Always runs
}
}
```
## 🧪 **Testing**
Use the test script to verify the locking mechanism:
```bash
pipeline/test-replica-locking.sh
```
This tests:
- ✅ Lock acquisition when available
- ✅ Lock blocking when unavailable
- ✅ Proper lock release
- ✅ System reset for next build
## 🔍 **Monitoring**
### **Check Build Status**
```bash
# Quick status check
kubectl get deployment buildah-external -n apps--droneio--prd
# Detailed status
kubectl describe deployment buildah-external -n apps--droneio--prd
```
### **Build Status Meanings**
- **READY 0/0**: No build running, system idle
- **READY 0/1**: Build starting, pod creating
- **READY 1/1**: Build active, pod running
- **READY 1/0**: Build ending, pod terminating
## 🎯 **Migration Notes**
This approach **replaces**:
- ❌ Lock file creation/deletion
- ❌ Lock timeout mechanisms
- ❌ Lock cleanup scripts
- ❌ Manual pod discovery
With **Kubernetes-native**:
- ✅ Atomic scaling operations
- ✅ Built-in conflict resolution
- ✅ Automatic resource management
- ✅ Observable state
The system is now **simpler, more reliable, and more efficient**! 🚀

View File

@@ -0,0 +1,250 @@
# Traefik Certificate Fix for drone.aipice.local
The error indicates that Traefik is serving a default certificate instead of a proper certificate for `drone.aipice.local`.
## 🔍 Root Cause
```
x509: certificate is valid for a7b8f3b8fd415b0fbd62e803b96eec90.d8282a75d7bf97aa2eb0bd7c2d927f85.traefik.default, not drone.aipice.local
```
This means:
- Traefik is using a default/fallback certificate
- No proper certificate configured for `drone.aipice.local`
- The domain doesn't match the certificate
## 🚀 Solutions
### Solution 1: Create Proper IngressRoute for Drone
Create a proper Traefik IngressRoute for your Drone CI:
```yaml
---
# drone-ingressroute.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: drone-ci
namespace: drone # Adjust to your Drone namespace
spec:
entryPoints:
- websecure
routes:
- match: Host(`drone.aipice.local`)
kind: Rule
services:
- name: drone-server # Your Drone service name
port: 80
tls:
certResolver: letsencrypt
domains:
- main: drone.aipice.local
---
# If you need a wildcard certificate for *.aipice.local
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wildcard-aipice-local
namespace: drone
spec:
secretName: wildcard-aipice-local-tls
issuerRef:
name: letsencrypt
kind: ClusterIssuer
commonName: "*.aipice.local"
dnsNames:
- "aipice.local"
- "*.aipice.local"
```
### Solution 2: Update Drone Helm Values (if using Helm)
If you're using Helm to deploy Drone:
```yaml
# drone-values.yaml
ingress:
enabled: true
className: traefik
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
cert-manager.io/cluster-issuer: letsencrypt
hosts:
- host: drone.aipice.local
paths:
- path: /
pathType: Prefix
tls:
- secretName: drone-aipice-local-tls
hosts:
- drone.aipice.local
```
### Solution 3: Manual Certificate Creation
Create a certificate manually for `drone.aipice.local`:
```yaml
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: drone-aipice-local-cert
namespace: drone
spec:
secretName: drone-tls-secret
issuerRef:
name: letsencrypt
kind: ClusterIssuer
commonName: drone.aipice.local
dnsNames:
- drone.aipice.local
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: drone-secure
namespace: drone
spec:
entryPoints:
- websecure
routes:
- match: Host(`drone.aipice.local`)
kind: Rule
services:
- name: drone-server
port: 80
tls:
secretName: drone-tls-secret
```
## 🔧 Quick Fix Commands
```bash
# 1. Check current Drone IngressRoute
kubectl get ingressroute -A | grep drone
# 2. Check current certificates
kubectl get certificates -A | grep drone
# 3. Check Traefik logs for certificate issues
kubectl logs -n traefik deployment/traefik | grep drone
# 4. Apply the fixed IngressRoute
kubectl apply -f drone-ingressroute.yaml
# 5. Wait for certificate to be issued
kubectl get certificate -n drone -w
```
## 🕵️ Debugging Steps
### Check Current Drone Service
```bash
# Find your Drone service
kubectl get svc -A | grep drone
# Check the service details
kubectl describe svc drone-server -n drone
```
### Check Traefik Configuration
```bash
# Check Traefik dashboard for routing
kubectl port-forward -n traefik svc/traefik 8080:8080
# Visit http://localhost:8080 to see routes
# Check IngressRoutes
kubectl get ingressroute -A -o yaml | grep -A 20 drone
```
### Verify Certificate Status
```bash
# Check certificate status
kubectl describe certificate -n drone
# Check certificate secret
kubectl get secret -n drone | grep tls
# Test certificate with openssl
openssl s_client -connect drone.aipice.local:443 -servername drone.aipice.local
```
## 🛠️ Alternative: Disable Certificate Verification
If you can't fix the certificate immediately, you can configure your Git service to skip certificate verification:
### For Gitea
```ini
# In Gitea app.ini
[webhook]
SKIP_TLS_VERIFY = true
ALLOWED_HOST_LIST = private
```
### For GitLab
```ruby
# In gitlab.rb
gitlab_rails['webhook_timeout'] = 30
gitlab_rails['outbound_requests_whitelist'] = ['192.168.100.0/24']
gitlab_rails['webhook_ssl_verification'] = false
```
### For GitHub (if self-hosted)
In webhook configuration:
- ☐ Enable SSL verification (uncheck this)
## 🎯 Complete Working Example
Here's a complete working configuration:
```yaml
---
# Complete Drone CI IngressRoute with proper TLS
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: drone-aipice-local
namespace: drone
labels:
app: drone-server
spec:
entryPoints:
- websecure
routes:
- match: Host(`drone.aipice.local`)
kind: Rule
services:
- name: drone-server
port: 80
middlewares:
- name: drone-headers
tls:
certResolver: letsencrypt
domains:
- main: drone.aipice.local
---
# Optional: Add security headers
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: drone-headers
namespace: drone
spec:
headers:
customRequestHeaders:
X-Forwarded-Proto: https
customResponseHeaders:
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
```
Apply this configuration and your webhooks should work properly with valid TLS certificates!

View File

@@ -0,0 +1,132 @@
// build-steps.libsonnet - Build-specific steps with replica-based scaling and locking
{
externalBuildahStep: {
name: "build-via-external-buildah",
image: "alpine:latest",
pull: "if-not-exists",
commands: [
"echo '🏗 Building via external Buildah deployment with replica scaling...'",
"echo 'Installing kubectl...'",
"apk add --no-cache curl",
"curl -LO \"https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl\"",
"chmod +x kubectl",
"mv kubectl /usr/local/bin/",
"echo '📦 Preparing build context...'",
"BUILD_ID=\"auth-service-${DRONE_BUILD_NUMBER}-$(date +%s)\"",
"echo \"Build ID: $BUILD_ID\"",
"echo '🔍 Checking current Buildah deployment replicas...'",
"CURRENT_REPLICAS=$(kubectl get deployment buildah-external -n apps--droneio--prd -o jsonpath='{.spec.replicas}')",
"echo \"Current replicas: $CURRENT_REPLICAS\"",
"echo '🔒 Attempting to scale up Buildah deployment (acts as build lock)...'",
"if [ \"$CURRENT_REPLICAS\" = \"0\" ]; then",
" echo \" No build running, scaling up deployment...\"",
" kubectl scale deployment buildah-external --replicas=1 -n apps--droneio--prd",
" echo \" Waiting for pod to be ready...\"",
" kubectl wait --for=condition=ready pod -l app=buildah-external -n apps--droneio--prd --timeout=120s",
"else",
" echo \" Build already running (replicas=$CURRENT_REPLICAS)! Aborting to prevent conflicts.\"",
" exit 1",
"fi",
"echo '<EFBFBD> Finding ready Buildah pod...'",
"BUILDAH_POD=$(kubectl get pods -n apps--droneio--prd -l app=buildah-external --field-selector=status.phase=Running -o jsonpath='{.items[0].metadata.name}')",
"if [ -z \"$BUILDAH_POD\" ]; then",
" echo \" No running Buildah pod found after scaling!\"",
" kubectl get pods -n apps--droneio--prd -l app=buildah-external",
" exit 1",
"fi",
"echo \" Using Buildah pod: $BUILDAH_POD\"",
"echo '📁 Creating build directory in Buildah pod...'",
"kubectl exec $BUILDAH_POD -n apps--droneio--prd -- mkdir -p \"/workspace/builds/$BUILD_ID\"",
"echo '📤 Copying source files to Buildah pod...'",
"tar czf - . | kubectl exec -i $BUILDAH_POD -n apps--droneio--prd -- tar xzf - -C \"/workspace/builds/$BUILD_ID\"",
"echo '🔨 Building container image with version from config...'",
"echo 'Reading version configuration...'",
". ./version.conf",
"DOCKER_TAG=\"$DOCKER_REPO:$BASE_VERSION.$DRONE_BUILD_NUMBER\"",
"echo \"Building with tag: $DOCKER_TAG\"",
"kubectl exec $BUILDAH_POD -n apps--droneio--prd -- sh -c \"cd /workspace/builds/$BUILD_ID && buildah build --isolation=chroot --storage-driver=vfs --format=docker --tag $DOCKER_TAG .\"",
"echo '📋 Listing built images...'",
"kubectl exec $BUILDAH_POD -n apps--droneio--prd -- buildah images | grep auth-service",
"echo \" Image built with tag: $DOCKER_TAG\"",
"echo '🧹 Cleaning up build directory...'",
"kubectl exec $BUILDAH_POD -n apps--droneio--prd -- rm -rf \"/workspace/builds/$BUILD_ID\"",
"echo ' External Buildah build completed successfully!'"
],
when: {
event: ["push"]
}
},
pushDockerStep: {
name: "push-docker-image",
image: "alpine:latest",
environment: {
DOCKER_USERNAME: { from_secret: "docker_username" },
DOCKER_PASSWORD: { from_secret: "docker_password" },
DOCKER_REGISTRY: { from_secret: "docker_registry" }
},
commands: [
"echo '📤 Pushing Docker image to registry...'",
"echo 'Installing kubectl...'",
"apk add --no-cache curl",
"curl -LO \"https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl\"",
"chmod +x kubectl && mv kubectl /usr/local/bin/",
"echo 'Reading version configuration...'",
". ./version.conf",
"DOCKER_TAG=\"$DOCKER_REPO:$BASE_VERSION.$DRONE_BUILD_NUMBER\"",
"echo \"Pushing image: $DOCKER_TAG\"",
"echo '🔍 Finding Buildah pod...'",
"BUILDAH_POD=$(kubectl get pods -n apps--droneio--prd -l app=buildah-external --field-selector=status.phase=Running -o jsonpath='{.items[0].metadata.name}')",
"echo \"Using Buildah pod: $BUILDAH_POD\"",
"echo '🔑 Authenticating with Docker registry...'",
"if [ -n \"$DOCKER_USERNAME\" ] && [ -n \"$DOCKER_PASSWORD\" ]; then",
" echo \"Logging into Docker registry...\"",
" kubectl exec $BUILDAH_POD -n apps--droneio--prd -- buildah login -u \"$DOCKER_USERNAME\" -p \"$DOCKER_PASSWORD\" \"$DOCKER_REGISTRY\"",
"else",
" echo \"No Docker credentials provided - attempting unauthenticated push\"",
"fi",
"echo '🚀 Pushing image to registry...'",
"kubectl exec $BUILDAH_POD -n apps--droneio--prd -- buildah push \"$DOCKER_TAG\"",
"echo \" Successfully pushed: $DOCKER_TAG\""
],
when: {
event: ["push"],
branch: ["main", "master"]
}
},
scaleDownStep: {
name: "scale-down-buildah",
image: "alpine:latest",
commands: [
"echo '🔽 Scaling down Buildah deployment (release build lock)...'",
"apk add --no-cache curl",
"curl -LO \"https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl\"",
"chmod +x kubectl && mv kubectl /usr/local/bin/",
"echo '📊 Current deployment status:'",
"kubectl get deployment buildah-external -n apps--droneio--prd",
"echo '🔽 Scaling down to 0 replicas...'",
"kubectl scale deployment buildah-external --replicas=0 -n apps--droneio--prd",
"echo ' Waiting for pods to terminate...'",
"kubectl wait --for=delete pod -l app=buildah-external -n apps--droneio--prd --timeout=60s || echo \"Pods may still be terminating\"",
"echo ' Buildah deployment scaled down - build lock released!'"
],
when: {
status: ["success", "failure"]
}
}
}

View File

@@ -0,0 +1,69 @@
# buildah-chart-override.yaml
# Override values for Drone chart to include signal-aware Buildah deployment
# If using Helm charts, these values override the default deployment
buildah-external:
enabled: true
replicaCount: 0 # Start with 0 replicas
image:
repository: quay.io/buildah/stable
tag: latest
pullPolicy: IfNotPresent
# Signal-aware command override
command: ["/bin/bash"]
args: ["-c", "trap 'echo Received SIGTERM, shutting down gracefully; exit 0' TERM; while true; do sleep 5 & wait $!; done"]
# Security context
securityContext:
privileged: true
runAsUser: 0
capabilities:
add:
- SYS_ADMIN
- MKNOD
- SYS_CHROOT
# Resource limits
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "2Gi"
cpu: "1000m"
# Pod security and termination
podSecurityContext:
runAsUser: 0
fsGroup: 0
# Graceful termination period
terminationGracePeriodSeconds: 10 # Reduced from default 30s
# Service account
serviceAccount:
name: "drone-buildah-sa"
# Environment variables
env:
- name: STORAGE_DRIVER
value: "vfs"
- name: BUILDAH_ISOLATION
value: "chroot"
# Volumes
volumes:
- name: workspace
emptyDir:
sizeLimit: 2Gi
- name: buildah-storage
emptyDir:
sizeLimit: 2Gi
volumeMounts:
- name: workspace
mountPath: /workspace
- name: buildah-storage
mountPath: /var/lib/containers

View File

@@ -0,0 +1,35 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: buildah-entrypoint
namespace: apps--droneio--prd
data:
entrypoint.sh: |
#!/bin/bash
# Signal-aware entrypoint for graceful shutdown
echo "🚀 Starting Buildah container with graceful shutdown support"
# Graceful shutdown handler
shutdown_handler() {
echo "📡 Received termination signal, shutting down gracefully..."
# Kill any running buildah processes
pkill -TERM buildah 2>/dev/null || true
# Give processes time to cleanup
sleep 2
echo "✅ Graceful shutdown complete"
exit 0
}
# Set up signal handlers
trap shutdown_handler SIGTERM SIGINT
# Keep container alive while handling signals
echo "⏳ Container ready, waiting for build requests..."
while true; do
sleep 10 &
wait $! # This wait will be interrupted by signals
done

View File

@@ -0,0 +1,68 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: buildah-external
namespace: apps--droneio--prd
labels:
app: buildah-external
purpose: on-demand-builds
spec:
replicas: 0 # Default to 0 - scaled up only during builds for atomic locking
selector:
matchLabels:
app: buildah-external
template:
metadata:
labels:
app: buildah-external
spec:
serviceAccountName: drone-buildah-sa
terminationGracePeriodSeconds: 5 # Faster termination
containers:
- name: buildah
image: quay.io/buildah/stable:latest
# Signal-aware command that responds to SIGTERM immediately
command: ["/bin/bash"]
args: ["-c", "trap 'exit 0' TERM; while true; do sleep 30 & wait $!; done"]
securityContext:
privileged: true
runAsUser: 0
capabilities:
add:
- SYS_ADMIN
- MKNOD
- SYS_CHROOT
volumeMounts:
- name: workspace
mountPath: /workspace
- name: buildah-storage
mountPath: /var/lib/containers
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "2Gi"
cpu: "1000m"
env:
- name: STORAGE_DRIVER
value: "vfs"
- name: BUILDAH_ISOLATION
value: "chroot"
# Readiness probe to ensure container is ready for builds
readinessProbe:
exec:
command:
- /bin/bash
- -c
- "buildah --version"
initialDelaySeconds: 5
periodSeconds: 10
volumes:
- name: workspace
emptyDir:
sizeLimit: 2Gi
- name: buildah-storage
emptyDir:
sizeLimit: 2Gi
restartPolicy: Always

View File

@@ -0,0 +1,65 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: buildah-external
namespace: apps--droneio--prd
labels:
app: buildah-external
purpose: on-demand-builds
spec:
# Default to 0 - scaled up only during builds for atomic locking
replicas: 0
selector:
matchLabels:
app: buildah-external
template:
metadata:
labels:
app: buildah-external
spec:
serviceAccountName: drone-buildah-sa
containers:
- name: buildah
image: quay.io/buildah/stable:latest
command: ["/bin/bash"]
args: ["/scripts/entrypoint.sh"]
securityContext:
privileged: true
runAsUser: 0
capabilities:
add:
- SYS_ADMIN
- MKNOD
- SYS_CHROOT
volumeMounts:
- name: entrypoint-script
mountPath: /scripts
readOnly: true
- name: workspace
mountPath: /workspace
- name: buildah-storage
mountPath: /var/lib/containers
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "2Gi"
cpu: "1200m"
env:
- name: STORAGE_DRIVER
value: "vfs"
- name: BUILDAH_ISOLATION
value: "chroot"
volumes:
- name: entrypoint-script
configMap:
name: buildah-entrypoint
defaultMode: 0755
- name: workspace
emptyDir:
sizeLimit: 2Gi
- name: buildah-storage
emptyDir:
sizeLimit: 2Gi
restartPolicy: Always

View File

@@ -0,0 +1,84 @@
// common.libsonnet - Shared configuration
{
environment: {
GIT_SSL_NO_VERIFY: "true"
},
cloneStep: {
name: "clone",
image: "alpine/git",
commands: [
"echo '🔄 Cloning repository...'",
"git config --global http.sslVerify false",
"git config --global user.email 'drone@aipice.local'",
"git config --global user.name 'Drone CI'",
"git clone https://gitea.aipice.local/AIPICE/auth-service.git . || echo 'Clone failed, but continuing...'",
"git checkout $DRONE_COMMIT || echo 'Checkout failed, using default'"
],
when: {
event: ["push"]
}
},
versionStep: {
name: "read-version",
image: "alpine:latest",
commands: [
"echo '📄 Reading version configuration...'",
"echo 'Sourcing version.conf...'",
". ./version.conf",
"echo \"BASE_VERSION: $BASE_VERSION\"",
"echo \"DOCKER_REPO: $DOCKER_REPO\"",
"DOCKER_TAG=\"$DOCKER_REPO:$BASE_VERSION.$DRONE_BUILD_NUMBER\"",
"echo \"DOCKER_TAG: $DOCKER_TAG\"",
"echo ' Version configuration loaded!'",
"echo \"Will build: $DOCKER_TAG\""
],
when: {
event: ["push"]
}
},
testStep: {
name: "test",
image: "alpine:latest",
commands: [
"echo '🧪 Starting tests...'",
"echo 'Repository ${DRONE_REPO}'",
"echo 'Branch ${DRONE_BRANCH}'",
"echo 'Owner ${DRONE_REPO_OWNER}'",
"echo 'Commit ${DRONE_COMMIT_SHA:0:8}'",
"echo 'Build ${DRONE_BUILD_NUMBER}'",
"echo 'Reading version info...'",
". ./version.conf",
"DOCKER_TAG=\"$DOCKER_REPO:$BASE_VERSION.$DRONE_BUILD_NUMBER\"",
"echo \"Docker tag will be: $DOCKER_TAG\"",
"echo 'Checking Dockerfile:'",
"cat Dockerfile || echo ' Dockerfile not found!'",
"echo ' Pre-build validation passed!'"
],
when: {
event: ["push"]
}
},
cleanupStep: {
name: "cleanup-build-lock",
image: "alpine:latest",
commands: [
"echo '🧹 Ensuring build lock cleanup...'",
"apk add --no-cache curl",
"curl -LO \"https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl\"",
"chmod +x kubectl && mv kubectl /usr/local/bin/",
"BUILDAH_POD=$(kubectl get pods -n apps--droneio--prd -l app=buildah-external --field-selector=status.phase=Running -o jsonpath='{.items[0].metadata.name}')",
"if [ -n \"$BUILDAH_POD\" ]; then kubectl exec $BUILDAH_POD -n apps--droneio--prd -- rm -f \"/workspace/locks/build-${DRONE_BUILD_NUMBER}.lock\" || echo \"Lock cleanup completed\"; echo \" Lock cleanup verified\"; else echo \" Buildah pod not available for cleanup\"; fi"
],
when: {
status: ["success", "failure"]
}
},
trigger: {
event: ["push", "pull_request"]
}
}

View File

@@ -0,0 +1,73 @@
#!/bin/bash
# Convert existing .drone.yml to modular Jsonnet structure
# This script helps migrate from YAML to factorized Jsonnet configuration
echo "🔄 Converting Drone configuration to modular Jsonnet..."
# Generate the final configuration from Jsonnet
echo "📝 Generating .drone.yml from Jsonnet..."
if command -v jsonnet >/dev/null 2>&1; then
jsonnet .drone.jsonnet > .drone.yml.generated
echo "✅ Generated .drone.yml.generated from Jsonnet"
echo ""
echo "📋 To use the new configuration:"
echo "1. Review: cat .drone.yml.generated"
echo "2. Test: python3 -c \"import yaml; yaml.safe_load(open('.drone.yml.generated'))\""
echo "3. Replace: mv .drone.yml.generated .drone.yml"
echo "4. Commit: git add .drone.jsonnet common.libsonnet build-steps.libsonnet .drone.yml"
else
echo "⚠️ jsonnet not installed. Installing..."
# Try to install jsonnet
if command -v apt-get >/dev/null 2>&1; then
sudo apt-get update && sudo apt-get install -y jsonnet
elif command -v apk >/dev/null 2>&1; then
apk add --no-cache jsonnet
elif command -v yum >/dev/null 2>&1; then
sudo yum install -y jsonnet
else
echo "❌ Cannot install jsonnet automatically"
echo "📖 Please install jsonnet manually:"
echo " - Ubuntu/Debian: sudo apt-get install jsonnet"
echo " - Alpine: apk add jsonnet"
echo " - CentOS/RHEL: sudo yum install jsonnet"
echo " - Or download from: https://github.com/google/jsonnet"
exit 1
fi
# Try generating again
if command -v jsonnet >/dev/null 2>&1; then
jsonnet .drone.jsonnet > .drone.yml.generated
echo "✅ Generated .drone.yml.generated from Jsonnet"
else
echo "❌ Failed to install jsonnet"
exit 1
fi
fi
echo ""
echo "🎯 Benefits of Jsonnet configuration:"
echo " ✅ Reusable components (common.libsonnet, build-steps.libsonnet)"
echo " ✅ Variables and functions"
echo " ✅ Conditional logic"
echo " ✅ Better maintainability"
echo " ✅ DRY principle"
echo ""
echo "📚 Files created:"
echo " - .drone.jsonnet (main configuration)"
echo " - common.libsonnet (shared steps and config)"
echo " - build-steps.libsonnet (build-specific logic)"
echo " - .drone.yml.generated (generated YAML)"
# Validate the generated YAML
if [ -f ".drone.yml.generated" ]; then
echo ""
echo "🔍 Validating generated YAML..."
if python3 -c "import yaml; yaml.safe_load(open('.drone.yml.generated'))" 2>/dev/null; then
echo "✅ Generated YAML is valid"
else
echo "❌ Generated YAML has syntax errors"
exit 1
fi
fi

View File

@@ -0,0 +1,62 @@
#!/bin/bash
# Deploy External Buildah Build System
# Sets up complete external build environment for Drone CI
set -e
echo "🚀 Deploying External Buildah Build System"
echo "============================================="
NAMESPACE="apps--droneio--prd"
# Check if namespace exists
if ! kubectl get namespace $NAMESPACE >/dev/null 2>&1; then
echo "❌ Namespace $NAMESPACE not found!"
exit 1
fi
echo "✅ Namespace $NAMESPACE verified"
# Deploy RBAC if not exists
echo "🔐 Setting up RBAC..."
if kubectl get serviceaccount drone-buildah-sa -n $NAMESPACE >/dev/null 2>&1; then
echo "✅ ServiceAccount already exists"
else
kubectl apply -f buildah-rbac.yaml
echo "✅ RBAC deployed"
fi
# Deploy external Buildah service
echo "🏗️ Deploying external Buildah service..."
kubectl apply -f buildah-external-deployment.yaml
echo "⏳ Waiting for Buildah pod to be ready..."
kubectl wait --for=condition=ready pod -l app=buildah-external -n $NAMESPACE --timeout=60s
# Update pod references
echo "🔄 Updating configuration files..."
./update-buildah-pod.sh
# Test the setup
echo "🧪 Testing build system..."
./manage-external-buildah.sh test
# Show status
echo ""
echo "📊 Deployment Status"
echo "===================="
kubectl get pods -n $NAMESPACE | grep -E "(NAME|buildah|drone)"
echo ""
echo "✅ External Buildah Build System deployed successfully!"
echo ""
echo "🎯 Next Steps:"
echo "1. Test with: ./manage-external-buildah.sh status"
echo "2. Use config: cp .drone.yml.external-buildah-production .drone.yml"
echo "3. Commit and push to trigger build"
echo ""
echo "📋 Available configurations:"
echo " .drone.yml.external-buildah - Basic external build"
echo " .drone.yml.external-buildah-advanced - Advanced with error handling"
echo " .drone.yml.external-buildah-production - Production-ready version"

View File

@@ -0,0 +1,29 @@
#!/bin/bash
echo "🚀 FORCE DRONE BUILD"
echo "==================="
echo "📅 $(date)"
echo
echo "Method: Empty commit (most reliable)"
echo "Repository: AIPICE/auth-service"
echo
read -p "Force build now? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]
then
echo "Creating empty commit..."
git commit --allow-empty -m "Force Drone build - $(date +'%Y-%m-%d %H:%M:%S')"
echo "Pushing to trigger build..."
git push
echo "✅ Build trigger sent!"
echo "Monitor build at: https://drone.aipice.local/AIPICE/auth-service"
echo "Watch build logs:"
echo " kubectl logs -f \$(kubectl get pods -n apps--droneio--prd | grep drone-runner | cut -d' ' -f1) -n apps--droneio--prd"
else
echo "Build not triggered."
fi

View File

@@ -0,0 +1,64 @@
#!/bin/bash
# Test graceful termination of signal-aware Buildah container
set -e
NAMESPACE="apps--droneio--prd"
DEPLOYMENT="buildah-external"
echo "🧪 Testing Graceful Termination"
echo "==============================="
# Scale up to create a pod
echo "🔼 Scaling up deployment..."
kubectl scale deployment $DEPLOYMENT --replicas=1 -n $NAMESPACE
echo "⏳ Waiting for pod to be ready..."
kubectl wait --for=condition=ready pod -l app=buildah-external -n $NAMESPACE --timeout=60s
POD_NAME=$(kubectl get pods -l app=buildah-external -n $NAMESPACE -o jsonpath='{.items[0].metadata.name}')
echo "📦 Testing pod: $POD_NAME"
# Test that the container is responsive
echo "🔍 Testing container responsiveness..."
kubectl exec $POD_NAME -n $NAMESPACE -- buildah --version
# Test graceful termination timing
echo "⏱️ Testing termination speed..."
START_TIME=$(date +%s)
echo "📤 Sending termination signal (scaling down)..."
kubectl scale deployment $DEPLOYMENT --replicas=0 -n $NAMESPACE
echo "⏳ Waiting for pod to terminate..."
kubectl wait --for=delete pod -l app=buildah-external -n $NAMESPACE --timeout=30s
END_TIME=$(date +%s)
TERMINATION_TIME=$((END_TIME - START_TIME))
echo "✅ Pod terminated in ${TERMINATION_TIME} seconds"
if [ $TERMINATION_TIME -le 10 ]; then
echo "🎉 Excellent! Graceful termination completed quickly (≤10s)"
elif [ $TERMINATION_TIME -le 30 ]; then
echo "✅ Good! Termination within acceptable time (≤30s)"
else
echo "⚠️ Slow termination (>30s) - may need optimization"
fi
echo ""
echo "🔍 Final deployment status:"
kubectl get deployment $DEPLOYMENT -n $NAMESPACE
echo ""
echo "📊 Termination Analysis:"
echo " ⏱️ Time: ${TERMINATION_TIME}s"
echo " 🎯 Target: <10s (excellent), <30s (good)"
echo " 📝 Method: Signal-aware bash loop with trap"
echo ""
if [ $TERMINATION_TIME -le 10 ]; then
echo "✅ Signal handling is working optimally!"
else
echo "💡 Consider further optimization if needed"
fi

View File

@@ -0,0 +1,104 @@
#!/bin/bash
# Test replica-based build locking mechanism
# This script demonstrates how the build system uses replicas for atomic locking
set -e
NAMESPACE="apps--droneio--prd"
DEPLOYMENT="buildah-external"
echo "🧪 Testing Replica-Based Build Locking"
echo "======================================"
# Function to get current replicas
get_replicas() {
kubectl get deployment $DEPLOYMENT -n $NAMESPACE -o jsonpath='{.spec.replicas}'
}
# Function to check if build can start
can_start_build() {
local replicas=$(get_replicas)
if [ "$replicas" = "0" ]; then
echo "✅ Build can start (replicas=0)"
return 0
else
echo "❌ Build already running (replicas=$replicas)"
return 1
fi
}
# Function to start build (scale up)
start_build() {
echo "🔒 Acquiring build lock (scaling up)..."
kubectl scale deployment $DEPLOYMENT --replicas=1 -n $NAMESPACE
echo "⏳ Waiting for pod to be ready..."
kubectl wait --for=condition=ready pod -l app=buildah-external -n $NAMESPACE --timeout=120s
echo "✅ Build lock acquired!"
}
# Function to end build (scale down)
end_build() {
echo "🔽 Releasing build lock (scaling down)..."
kubectl scale deployment $DEPLOYMENT --replicas=0 -n $NAMESPACE
echo "⏳ Waiting for pods to terminate..."
kubectl wait --for=delete pod -l app=buildah-external -n $NAMESPACE --timeout=60s || echo "Pods may still be terminating"
echo "✅ Build lock released!"
}
# Test sequence
echo "📊 Current deployment status:"
kubectl get deployment $DEPLOYMENT -n $NAMESPACE
echo ""
echo "🔍 Checking if build can start..."
if can_start_build; then
echo ""
echo "🚀 Starting test build..."
start_build
echo ""
echo "📊 Deployment during build:"
kubectl get deployment $DEPLOYMENT -n $NAMESPACE
kubectl get pods -l app=buildah-external -n $NAMESPACE
echo ""
echo "🔍 Testing concurrent build attempt..."
if can_start_build; then
echo "🚨 ERROR: Concurrent build should be blocked!"
exit 1
else
echo "✅ Concurrent build correctly blocked!"
fi
echo ""
echo "🛑 Ending test build..."
end_build
echo ""
echo "📊 Final deployment status:"
kubectl get deployment $DEPLOYMENT -n $NAMESPACE
echo ""
echo "🔍 Verifying build can start again..."
if can_start_build; then
echo "✅ Build system ready for next build!"
else
echo "🚨 ERROR: Build system not properly reset!"
exit 1
fi
else
echo ""
echo "⚠️ Cannot test - build already running"
echo "Use: kubectl scale deployment $DEPLOYMENT --replicas=0 -n $NAMESPACE"
fi
echo ""
echo "🎉 Replica-based locking test completed successfully!"
echo ""
echo "💡 Benefits:"
echo " ✅ Atomic operations (no race conditions)"
echo " ✅ No lock files to manage"
echo " ✅ Kubernetes-native approach"
echo " ✅ Resource efficient (only runs when needed)"
echo " ✅ Automatic cleanup on failure"