|
| 1 | +# Fleet Register |
| 2 | + |
| 3 | +A lightweight Go HTTP server that monitors IBM Cloud Code Engine fleet workers by tracking their lifecycle events in an Excel file. |
| 4 | + |
| 5 | +## Use Case |
| 6 | + |
| 7 | +This application is deployed as a Code Engine application to monitor fleet workers. Fleet workers call the `/register` endpoint when they start and the `/deregister` endpoint before they shut down. The application maintains a persistent Excel file tracking all worker activity, including registration and completion timestamps. |
| 8 | + |
| 9 | +**Deployment Flow:** |
| 10 | +1. Deploy this app as a Code Engine application with persistent storage |
| 11 | +2. Configure the fleet with register/deregister hooks pointing to this app |
| 12 | +3. Fleet workers automatically report their status throughout their lifecycle |
| 13 | + |
| 14 | +## Endpoints |
| 15 | + |
| 16 | +- `POST /register` |
| 17 | + Creates a row in `fleet-register.xlsx` with status `running` and records the registration timestamp. |
| 18 | + |
| 19 | +- `POST /deregister` |
| 20 | + Updates the matching row by `worker_name` and `worker_ip` to `completed` and records the completion timestamp. |
| 21 | + If no row exists, it creates a new row with status `completed`. |
| 22 | + |
| 23 | +- `GET /download` |
| 24 | + Downloads the Excel file. |
| 25 | + |
| 26 | +## Request body |
| 27 | + |
| 28 | +```json |
| 29 | +{ |
| 30 | + "worker_name": "worker-01", |
| 31 | + "worker_ip": "192.168.1.10" |
| 32 | +} |
| 33 | +``` |
| 34 | + |
| 35 | +## Deployment |
| 36 | + |
| 37 | +### Code Engine (Production) |
| 38 | + |
| 39 | +1. **Deploy the application with persistent storage:** |
| 40 | + ```bash |
| 41 | + ibmcloud ce app create --name fleet-workers \ |
| 42 | + --build-dockerfile Dockerfile \ |
| 43 | + --build-source . \ |
| 44 | + --mount-data-store /fleet-workers=fleet-data |
| 45 | + ``` |
| 46 | + |
| 47 | +2. **Run fleet with hooks:** |
| 48 | + |
| 49 | + The `run` script automatically retrieves the app URL and creates a fleet with register/deregister hooks: |
| 50 | + ```bash |
| 51 | + ./run |
| 52 | + ``` |
| 53 | + |
| 54 | + Or manually create a fleet: |
| 55 | + ```bash |
| 56 | + APP_URL=$(ibmcloud ce app get --name fleet-workers -o url) |
| 57 | + |
| 58 | + PREHOOK="curl -X POST \${APP_URL}/register -H 'Content-Type: application/json' -d '{\"worker_name\":\"\${CE_WORKER_NAME}\",\"worker_ip\":\"\${CE_WORKER_IP}\"}'" |
| 59 | + |
| 60 | + POSTHOOK="curl -X POST \${APP_URL}/deregister -H 'Content-Type: application/json' -d '{\"worker_name\":\"\${CE_WORKER_NAME}\",\"worker_ip\":\"\${CE_WORKER_IP}\"}'" |
| 61 | + |
| 62 | + ibmcloud code-engine fleet create --name my-fleet \ |
| 63 | + --tasks-state-store fleet-task-store \ |
| 64 | + --subnetpool-name fleet-subnetpool \ |
| 65 | + --image registry.access.redhat.com/ubi10/ubi-minimal \ |
| 66 | + --max-scale 100 \ |
| 67 | + --command="sleep" \ |
| 68 | + --arg "30" \ |
| 69 | + --tasks 100 \ |
| 70 | + --env __CE_INTERNAL_HOOK_AFTER_STARTUP="${PREHOOK}" \ |
| 71 | + --env __CE_INTERNAL_HOOK_AFTER_STARTUP_RETRY_LIMIT=3 \ |
| 72 | + --env __CE_INTERNAL_HOOK_AFTER_STARTUP_MAX_EXECUTION_TIME=30m \ |
| 73 | + --env __CE_INTERNAL_HOOK_BEFORE_SHUTDOWN="${POSTHOOK}" \ |
| 74 | + --env __CE_INTERNAL_HOOK_BEFORE_SHUTDOWN_RETRY_LIMIT=3 \ |
| 75 | + --env __CE_INTERNAL_HOOK_BEFORE_SHUTDOWN_MAX_EXECUTION_TIME=30m \ |
| 76 | + --env APP_URL="${APP_URL}" \ |
| 77 | + --cpu 2 \ |
| 78 | + --memory 4G |
| 79 | + ``` |
| 80 | + |
| 81 | +### Local Development |
| 82 | + |
| 83 | +```bash |
| 84 | +go run . |
| 85 | +``` |
| 86 | + |
| 87 | +Server listens on `:8080`. |
| 88 | + |
| 89 | +### Docker |
| 90 | + |
| 91 | +```bash |
| 92 | +docker build -t fleet-register . |
| 93 | +docker run -p 8080:8080 -v fleet-data:/fleet-workers fleet-register |
| 94 | +``` |
| 95 | + |
| 96 | +The Excel file is saved to `/fleet-workers/fleet-register.xlsx` and persisted in the volume. |
| 97 | + |
| 98 | +## Examples |
| 99 | + |
| 100 | +Register a worker: |
| 101 | + |
| 102 | +```bash |
| 103 | +curl -X POST http://localhost:8080/register \ |
| 104 | + -H "Content-Type: application/json" \ |
| 105 | + -d '{ |
| 106 | + "worker_name": "worker-01", |
| 107 | + "worker_ip": "192.168.1.10" |
| 108 | + }' |
| 109 | +``` |
| 110 | + |
| 111 | +Deregister a worker: |
| 112 | + |
| 113 | +```bash |
| 114 | +curl -X POST http://localhost:8080/deregister \ |
| 115 | + -H "Content-Type: application/json" \ |
| 116 | + -d '{ |
| 117 | + "worker_name": "worker-01", |
| 118 | + "worker_ip": "192.168.1.10" |
| 119 | + }' |
| 120 | +``` |
| 121 | + |
| 122 | +Download the workbook: |
| 123 | + |
| 124 | +```bash |
| 125 | +curl -O -J http://localhost:8080/download |
| 126 | +``` |
| 127 | + |
| 128 | +## Excel file |
| 129 | + |
| 130 | +The server automatically creates `fleet-register.xlsx` in the project root (or `/fleet-workers/` in Docker) if it does not exist. |
| 131 | + |
| 132 | +The workbook contains one sheet named `Workers` with these columns: |
| 133 | + |
| 134 | +- `worker_name` - Name of the worker |
| 135 | +- `worker_ip` - IP address of the worker |
| 136 | +- `status` - Current status (running/completed) |
| 137 | +- `registered_at` - Timestamp when the worker was registered (ISO 8601 format) |
| 138 | +- `completed_at` - Timestamp when the worker completed (ISO 8601 format) |
0 commit comments