Initialisation depot
This commit is contained in:
0
arti-api/auth-service/pipeline/.drone.yml
Normal file
0
arti-api/auth-service/pipeline/.drone.yml
Normal file
0
arti-api/auth-service/pipeline/.drone.yml.generated
Normal file
0
arti-api/auth-service/pipeline/.drone.yml.generated
Normal file
164
arti-api/auth-service/pipeline/DRONE-SETUP.md
Normal file
164
arti-api/auth-service/pipeline/DRONE-SETUP.md
Normal 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
|
||||
```
|
||||
171
arti-api/auth-service/pipeline/EXTERNAL-BUILDAH-SYSTEM.md
Normal file
171
arti-api/auth-service/pipeline/EXTERNAL-BUILDAH-SYSTEM.md
Normal 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!
|
||||
132
arti-api/auth-service/pipeline/GIT-WEBHOOK-CONFIG.md
Normal file
132
arti-api/auth-service/pipeline/GIT-WEBHOOK-CONFIG.md
Normal 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
|
||||
```
|
||||
144
arti-api/auth-service/pipeline/GRACEFUL-TERMINATION.md
Normal file
144
arti-api/auth-service/pipeline/GRACEFUL-TERMINATION.md
Normal 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! 🎉
|
||||
169
arti-api/auth-service/pipeline/JSONNET-GUIDE.md
Normal file
169
arti-api/auth-service/pipeline/JSONNET-GUIDE.md
Normal 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! 🚀
|
||||
306
arti-api/auth-service/pipeline/MULTI-DOMAIN-GUIDE.md
Normal file
306
arti-api/auth-service/pipeline/MULTI-DOMAIN-GUIDE.md
Normal 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!
|
||||
67
arti-api/auth-service/pipeline/PIPELINE-README.md
Normal file
67
arti-api/auth-service/pipeline/PIPELINE-README.md
Normal 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
|
||||
429
arti-api/auth-service/pipeline/README.md
Normal file
429
arti-api/auth-service/pipeline/README.md
Normal 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
|
||||
152
arti-api/auth-service/pipeline/REPLICA-LOCKING.md
Normal file
152
arti-api/auth-service/pipeline/REPLICA-LOCKING.md
Normal 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**! 🚀
|
||||
250
arti-api/auth-service/pipeline/TRAEFIK-DRONE-TLS-FIX.md
Normal file
250
arti-api/auth-service/pipeline/TRAEFIK-DRONE-TLS-FIX.md
Normal 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!
|
||||
132
arti-api/auth-service/pipeline/build-steps.libsonnet
Normal file
132
arti-api/auth-service/pipeline/build-steps.libsonnet
Normal 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"]
|
||||
}
|
||||
}
|
||||
}
|
||||
69
arti-api/auth-service/pipeline/buildah-chart-override.yaml
Normal file
69
arti-api/auth-service/pipeline/buildah-chart-override.yaml
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
84
arti-api/auth-service/pipeline/common.libsonnet
Normal file
84
arti-api/auth-service/pipeline/common.libsonnet
Normal 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"]
|
||||
}
|
||||
}
|
||||
73
arti-api/auth-service/pipeline/convert-to-jsonnet.sh
Executable file
73
arti-api/auth-service/pipeline/convert-to-jsonnet.sh
Executable 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
|
||||
62
arti-api/auth-service/pipeline/deploy-external-buildah.sh
Executable file
62
arti-api/auth-service/pipeline/deploy-external-buildah.sh
Executable 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"
|
||||
29
arti-api/auth-service/pipeline/force-build.sh
Executable file
29
arti-api/auth-service/pipeline/force-build.sh
Executable 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
|
||||
64
arti-api/auth-service/pipeline/test-graceful-termination.sh
Executable file
64
arti-api/auth-service/pipeline/test-graceful-termination.sh
Executable 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
|
||||
104
arti-api/auth-service/pipeline/test-replica-locking.sh
Executable file
104
arti-api/auth-service/pipeline/test-replica-locking.sh
Executable 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"
|
||||
Reference in New Issue
Block a user