- Add Codeberg Ansible collection link to API/GraphQL docs and Terraform guide - Un-skip the previously-disabled DevicePollerWorker tests that still pass - Expand MibController, CnMaestro.Sync, CheckWorker, ActivityFeed, MobileController, JobCleanupTask tests - New UploadMibs Mix task test covering arg validation and upload paths - Set :mib_dir in test config so MibController upload/delete flows can exercise the real on-disk paths against a writable tmp directory
108 lines
3.4 KiB
Markdown
108 lines
3.4 KiB
Markdown
# Coverages over the Towerops API (Terraform-friendly)
|
|
|
|
Towerops exposes a resourceful REST API for RF coverage predictions
|
|
that's stable enough to drive from Terraform, Ansible, or any
|
|
infrastructure-as-code tool. All endpoints live under `/api/v1/` and
|
|
use Bearer-token auth scoped to a single organization.
|
|
|
|
> Looking for an Ansible-native interface? The official Towerops Ansible
|
|
> collection wraps these endpoints with idempotent modules:
|
|
> <https://codeberg.org/towerops/ansible>.
|
|
|
|
## Authentication
|
|
|
|
Mint a token from **Settings → API tokens**. Send it as:
|
|
|
|
```
|
|
Authorization: Bearer towerops_<token>
|
|
```
|
|
|
|
The token is org-scoped — every endpoint reads/writes inside that
|
|
org only.
|
|
|
|
## Resources
|
|
|
|
| Method | Path | Purpose |
|
|
|---------|---------------------------------------|---------|
|
|
| GET | `/api/v1/coverages` | List all coverages in the org. |
|
|
| POST | `/api/v1/coverages` | Create a coverage. The compute pipeline is queued automatically. |
|
|
| GET | `/api/v1/coverages/:id` | Read a single coverage including current `status` / `progress_pct`. |
|
|
| PATCH | `/api/v1/coverages/:id` | Update editable fields (does not auto-recompute). |
|
|
| DELETE | `/api/v1/coverages/:id` | Delete a coverage and its on-disk rasters. |
|
|
| POST | `/api/v1/coverages/:id/recompute` | Re-run the compute pipeline. Returns `202` with `status: "queued"`. |
|
|
| GET | `/api/v1/coverages/:id/kmz` | Download a KMZ overlay for Google Earth (returns `409` until `status: "ready"`). |
|
|
|
|
## Create payload
|
|
|
|
```json
|
|
{
|
|
"coverage": {
|
|
"name": "North sector 5 GHz",
|
|
"site_id": "1f4...uuid",
|
|
"antenna_slug": "rf-elements-twistport-symmetrical-horn-30",
|
|
"frequency_ghz": 5.8,
|
|
"tx_power_dbm": 22.0,
|
|
"height_agl_ft": 100,
|
|
"azimuth_deg": 0,
|
|
"downtilt_deg": 0,
|
|
"radius_mi": 4
|
|
}
|
|
}
|
|
```
|
|
|
|
Imperial inputs are accepted via the virtual fields shown above; the
|
|
schema converts them to SI before validation.
|
|
|
|
## Polling for `:ready`
|
|
|
|
Compute is asynchronous. After `POST` you'll receive `status:
|
|
"queued"`; the worker transitions through `"computing"` to
|
|
`"ready"` (or `"failed"`). Terraform providers can poll with
|
|
`GET /api/v1/coverages/:id` until `status == "ready"` before
|
|
declaring the resource healthy.
|
|
|
|
## Terraform example
|
|
|
|
A Terraform provider for Towerops isn't published yet, but a
|
|
hand-rolled `restapi` provider works today:
|
|
|
|
```hcl
|
|
terraform {
|
|
required_providers {
|
|
restapi = { source = "Mastercard/restapi", version = "~> 1.18" }
|
|
}
|
|
}
|
|
|
|
provider "restapi" {
|
|
uri = "https://app.towerops.com"
|
|
write_returns_object = true
|
|
headers = {
|
|
Authorization = "Bearer ${var.towerops_token}"
|
|
Content-Type = "application/json"
|
|
}
|
|
}
|
|
|
|
resource "restapi_object" "north_sector" {
|
|
path = "/api/v1/coverages"
|
|
id_attribute = "id"
|
|
|
|
data = jsonencode({
|
|
coverage = {
|
|
name = "North sector 5 GHz"
|
|
site_id = var.site_id
|
|
antenna_slug = "rf-elements-twistport-symmetrical-horn-30"
|
|
frequency_ghz = 5.8
|
|
tx_power_dbm = 22.0
|
|
height_agl_ft = 100
|
|
azimuth_deg = 0
|
|
downtilt_deg = 0
|
|
radius_mi = 4
|
|
}
|
|
})
|
|
}
|
|
```
|
|
|
|
`terraform apply` creates the coverage; `terraform destroy` deletes
|
|
it. Updates flow through `PATCH`. Use `terraform_data` + a
|
|
`provisioner` if you need to wait on `status = "ready"` before
|
|
proceeding.
|