# Tanzu Deployer UI - Angular Frontend A modern, dark-themed Angular 19.1 frontend for deploying applications to Tanzu/Cloud Foundry environments. ## Features - ✅ **Modern Dark Theme**: Sleek GitHub-inspired dark UI with blue/purple gradients - ✅ **Simple Form Interface**: Easy-to-use deployment form with all Tanzu configuration fields - ✅ **Modern File Upload**: Beautiful drag-and-drop style file upload buttons with SVG icons - ✅ **Chunked File Upload**: Handles large JAR files using Base64-encoded chunks (compatible with Java proxy) - ✅ **Real-time Progress**: Visual progress bar showing upload and deployment status - ✅ **Live Logs**: Collapsible terminal-style output window displaying deployment logs - ✅ **Responsive Design**: Works seamlessly on desktop, tablet, and mobile devices - ✅ **Secure**: Password fields are masked, follows Angular security best practices - ✅ **Configurable**: Environment-based configuration for all settings - ✅ **Production Ready**: Includes nginx configuration and Helm chart for K8s deployment ## Configuration All application settings are managed via environment files: **`src/environments/environment.ts`** (Development): ```typescript export const environment = { production: false, apiBase: '/api/cf', // API endpoint base URL chunkSize: 1048576, // Chunk size in bytes (1MB) enableSslValidation: false, // Show/hide SSL validation checkbox pollInterval: 5000, // Poll interval in milliseconds maxPollAttempts: 120, // Max polling attempts (10 minutes) defaultLogsExpanded: true, // Logs expanded by default showDebugInfo: false // Show debug information }; ``` **`src/environments/environment.prod.ts`** (Production): - Same structure as development - Used when building with `--configuration production` ### Customizing Configuration To customize the application behavior: 1. Edit `src/environments/environment.ts` for development 2. Edit `src/environments/environment.prod.ts` for production 3. Rebuild the application **Common Customizations:** - **Enable SSL Validation Checkbox**: Set `enableSslValidation: true` - **Change Chunk Size**: Set `chunkSize: 2097152` (2MB) - **Increase Poll Time**: Set `maxPollAttempts: 240` (20 minutes) - **Change API Endpoint**: Set `apiBase: 'https://api.example.com/cf'` ## Quick Start ### Local Development 1. **Install dependencies:** ```bash npm install ``` 2. **Start development server:** ```bash npm start ``` 3. **Open browser:** Navigate to `http://localhost:4200` ### Build for Production ```bash npm run build:prod ``` Built files will be in `dist/cf-deployer-ui/browser/` ## Docker Deployment ### Build Docker Image ```bash docker build -t cf-deployer-ui:latest . ``` ### Run Docker Container ```bash docker run -d \ -p 8080:80 \ -e BACKEND_URL=http://cf-deployer-backend:8080 \ --name cf-deployer-ui \ cf-deployer-ui:latest ``` **Environment Variables:** - `BACKEND_URL`: URL of the CF Deployer backend API (default: `http://localhost:8080`) ## Kubernetes Deployment ### Prerequisites - Kubernetes cluster - Helm 3.x installed - Docker image pushed to registry ### Deploy with Helm 1. **Update values.yaml:** ```yaml image: repository: your-registry/cf-deployer-ui tag: "1.0.0" backend: url: "http://cf-deployer-backend:8080" ingress: enabled: true hosts: - host: cf-deployer.example.com paths: - path: / pathType: Prefix ``` 2. **Install the chart:** ```bash helm install cf-deployer-ui ./helm ``` 3. **Upgrade the chart:** ```bash helm upgrade cf-deployer-ui ./helm ``` 4. **Uninstall:** ```bash helm uninstall cf-deployer-ui ``` ### Helm Configuration Options | Parameter | Description | Default | |-----------|-------------|---------| | `replicaCount` | Number of replicas | `2` | | `image.repository` | Docker image repository | `cf-deployer-ui` | | `image.tag` | Docker image tag | `latest` | | `service.type` | Kubernetes service type | `ClusterIP` | | `service.port` | Service port | `80` | | `backend.url` | Backend API URL | `http://cf-deployer-backend:8080` | | `ingress.enabled` | Enable ingress | `false` | | `resources.limits.cpu` | CPU limit | `500m` | | `resources.limits.memory` | Memory limit | `512Mi` | ## Usage ### Deployment Flow 1. **Fill in Cloud Foundry Details:** - API Endpoint (e.g., `https://api.cf.example.com`) - Username and Password - Organization and Space - Application Name - Skip SSL Validation (if needed) 2. **Select Files:** - JAR File: Your application JAR - Manifest File: Cloud Foundry manifest.yml 3. **Deploy:** - Click "Deploy to Cloud Foundry" - Watch progress bar and logs - Wait for completion ### Screenshots **Main Form:** - Clean, responsive form with all required fields - File upload with size display - SSL validation checkbox **Progress Tracking:** - Visual progress bar (0-100%) - Current step indicator - Status badges (IN_PROGRESS, COMPLETED, FAILED) **Logs Output:** - Collapsible terminal-style output - Timestamped log entries - Auto-scroll to latest logs ## Architecture ### How It Works The frontend mimics the behavior of `deploy-chunked-simple.sh`: 1. **Initialize Upload Session:** ``` POST /api/cf/upload/init → Returns uploadSessionId ``` 2. **Upload Files in Chunks:** - Splits files into 1MB chunks - Base64 encodes each chunk (for Java proxy compatibility) - Uploads via: ``` POST /api/cf/upload/chunk?uploadSessionId=...&fileType=...&chunkIndex=...&totalChunks=...&fileName=... Headers: Content-Type: text/plain, X-Chunk-Encoding: base64 Body: Base64 chunk data ``` 3. **Finalize Upload:** ``` POST /api/cf/upload/finalize?uploadSessionId=...&async=true ``` 4. **Poll Deployment Status:** ``` GET /api/cf/deployment/status/{uploadSessionId} (Every 5 seconds until COMPLETED or FAILED) ``` ### Why Base64 Encoding? The frontend sends chunks as Base64-encoded text because: - It goes through a Java proxy that reads `@RequestBody String` - Binary data gets corrupted when read as String - Base64 ensures safe text transport through the proxy - Backend automatically decodes Base64 back to binary ## Project Structure ``` frontend/ ├── src/ │ ├── app/ │ │ ├── app.component.ts # Main component with form logic │ │ ├── app.component.html # Template with form UI │ │ ├── app.component.css # Component styles │ │ └── deploy.service.ts # API service │ ├── index.html # Main HTML file │ ├── main.ts # Bootstrap file │ └── styles.css # Global styles ├── helm/ # Helm chart │ ├── Chart.yaml │ ├── values.yaml │ └── templates/ │ ├── deployment.yaml │ ├── service.yaml │ ├── ingress.yaml │ └── _helpers.tpl ├── nginx.conf # nginx configuration ├── Dockerfile # Multi-stage Docker build ├── angular.json # Angular CLI configuration ├── package.json # NPM dependencies └── tsconfig.json # TypeScript configuration ``` ## Development ### Prerequisites - Node.js 20.x or higher - npm 10.x or higher - Angular CLI 19.x ### Install Angular CLI ```bash npm install -g @angular/cli@19 ``` ### Code Structure **app.component.ts:** - Handles form state and validation - Manages file uploads and chunking - Polls deployment status - Updates progress and logs **deploy.service.ts:** - Encapsulates all HTTP API calls - Returns RxJS Observables converted to Promises - Handles Base64 encoding headers **Styling:** - Responsive grid layout - Mobile-first design - Terminal-style logs with custom scrollbar - Gradient progress bar ## Troubleshooting ### CORS Errors If you see CORS errors in the browser console: 1. **Development:** Configure proxy in `angular.json`: ```json { "serve": { "options": { "proxyConfig": "proxy.conf.json" } } } ``` Create `proxy.conf.json`: ```json { "/api": { "target": "http://localhost:8080", "secure": false } } ``` 2. **Production:** nginx handles proxying (already configured) ### File Upload Fails - Check that backend is running and accessible - Verify `BACKEND_URL` environment variable - Check browser console for error messages - Enable DEBUG_MODE in backend to see detailed logs ### Deployment Timeout - Default timeout is 10 minutes (120 attempts × 5 seconds) - Increase `maxAttempts` in `pollDeploymentStatus()` if needed - Check backend logs for actual deployment status ## Browser Support - Chrome/Edge (latest) - Firefox (latest) - Safari (latest) - Mobile browsers (iOS Safari, Chrome Android) ## License MIT License - see main project README