Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 714320c018 | |||
| fa8ba6fac1 |
@@ -1,502 +0,0 @@
|
|||||||
# MCP v2 -- Multi-Node Control Plane
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
MCP v2 introduces multi-node orchestration with a master/agent topology.
|
|
||||||
The CLI no longer dials agents directly. A dedicated **mcp-master** daemon
|
|
||||||
coordinates deployments across nodes, handles cross-node concerns (edge
|
|
||||||
routing, certificate provisioning, DNS), and serves as the single control
|
|
||||||
point for the platform.
|
|
||||||
|
|
||||||
### Motivation
|
|
||||||
|
|
||||||
v1 deployed successfully on a single node (rift) but exposed operational
|
|
||||||
pain points as services needed public-facing routes through svc:
|
|
||||||
|
|
||||||
- **Manual edge routing**: Exposing mcq.metacircular.net required hand-editing
|
|
||||||
mc-proxy's TOML config on svc, provisioning a TLS cert manually, updating
|
|
||||||
the SQLite database when the config and database diverged, and debugging
|
|
||||||
silent failures. Every redeployment risked breaking the public route.
|
|
||||||
|
|
||||||
- **Dynamic port instability**: The route system assigns ephemeral host ports
|
|
||||||
that change on every deploy. svc's mc-proxy pointed at a specific port
|
|
||||||
(e.g., `100.95.252.120:48080`), which went stale after redeployment.
|
|
||||||
Container ports are also localhost-only under rootless podman, requiring
|
|
||||||
explicit Tailscale IP bindings for external access.
|
|
||||||
|
|
||||||
- **$PORT env override conflict**: The mcdsl config loader overrides
|
|
||||||
`listen_addr` from `$PORT` when routes are present. This meant containers
|
|
||||||
ignored their configured port and listened on the route-allocated one
|
|
||||||
instead, breaking explicit port mappings that expected the config port.
|
|
||||||
|
|
||||||
- **Cert chain issues**: mc-proxy requires full certificate chains (leaf +
|
|
||||||
intermediates). Certs provisioned outside the standard metacrypt flow
|
|
||||||
were leaf-only and caused silent TLS handshake failures (`client_bytes=7
|
|
||||||
backend_bytes=0` with no error logged).
|
|
||||||
|
|
||||||
- **mc-proxy database divergence**: mc-proxy persists routes in SQLite.
|
|
||||||
Routes added via the admin API override the TOML config. Editing the TOML
|
|
||||||
alone had no effect until the database was manually updated -- a failure
|
|
||||||
mode that took hours to diagnose.
|
|
||||||
|
|
||||||
- **No cross-node coordination**: The v1 CLI talks directly to individual
|
|
||||||
agents. There is no mechanism for one agent to tell another "set up a
|
|
||||||
route for this service." Every cross-node operation was manual.
|
|
||||||
|
|
||||||
v2 addresses all of these by making the master the single coordination
|
|
||||||
point for deployments, with agents handling local concerns (containers,
|
|
||||||
mc-proxy routes, cert provisioning) on instruction from the master.
|
|
||||||
|
|
||||||
### What Changes from v1
|
|
||||||
|
|
||||||
| Concern | v1 | v2 |
|
|
||||||
|---------|----|----|
|
|
||||||
| CLI target | CLI dials agents directly | CLI dials the master |
|
|
||||||
| Node awareness | CLI routes by `node` field in service defs | Master owns the node registry |
|
|
||||||
| Service definitions | Live on operator workstation | Pushed to master, which distributes to agents |
|
|
||||||
| Edge routing | Manual mc-proxy config on svc | Master coordinates agent-to-agent setup |
|
|
||||||
| Cert provisioning | Agent provisions for local mc-proxy only | Any agent can provision certs (edge included) |
|
|
||||||
| DNS registration | Agent registers records on deploy | Master coordinates DNS across zones |
|
|
||||||
|
|
||||||
### What Stays the Same
|
|
||||||
|
|
||||||
The agent's core responsibilities are unchanged: it manages containers via
|
|
||||||
podman, stores its local registry in SQLite, monitors for drift, and alerts
|
|
||||||
the operator. The agent gains new RPCs for edge routing but does not become
|
|
||||||
aware of other nodes -- the master handles all cross-node coordination.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Topology
|
|
||||||
|
|
||||||
```
|
|
||||||
Operator workstation (vade)
|
|
||||||
┌──────────────────────────┐
|
|
||||||
│ mcp (CLI) │
|
|
||||||
│ │
|
|
||||||
│ gRPC ───────────────────┼─── overlay ───┐
|
|
||||||
└──────────────────────────┘ │
|
|
||||||
▼
|
|
||||||
Master node (straylight)
|
|
||||||
┌──────────────────────────────────────────────────────┐
|
|
||||||
│ mcp-master │
|
|
||||||
│ ├── node registry (all nodes, roles, addresses) │
|
|
||||||
│ ├── service definitions (pushed from CLI) │
|
|
||||||
│ └── deployment coordinator │
|
|
||||||
│ │
|
|
||||||
│ mcp-agent │
|
|
||||||
│ ├── mcns container │
|
|
||||||
│ ├── metacrypt container │
|
|
||||||
│ ├── mcr container │
|
|
||||||
│ └── mc-proxy (straylight) │
|
|
||||||
└──────────┬──────────────────────────┬────────────────┘
|
|
||||||
│ │
|
|
||||||
overlay overlay
|
|
||||||
│ │
|
|
||||||
▼ ▼
|
|
||||||
Worker node (rift) Edge node (svc)
|
|
||||||
┌─────────────────────┐ ┌─────────────────────────┐
|
|
||||||
│ mcp-agent │ │ mcp-agent │
|
|
||||||
│ ├── exo │ │ ├── mc-proxy (svc) │
|
|
||||||
│ ├── mcq │ │ └── (edge routes only) │
|
|
||||||
│ ├── mcdoc │ │ │
|
|
||||||
│ ├── sgard │ │ Edge routes: │
|
|
||||||
│ ├── kls │ │ mcq.metacircular.net │
|
|
||||||
│ └── mc-proxy │ │ mcdoc.metacircular.net │
|
|
||||||
│ (rift) │ │ exo.metacircular.net │
|
|
||||||
└─────────────────────┘ │ sgard.metacircular.net │
|
|
||||||
└─────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### Node Roles
|
|
||||||
|
|
||||||
| Role | Purpose | Nodes |
|
|
||||||
|------|---------|-------|
|
|
||||||
| **master** | Runs mcp-master + mcp-agent. Hosts core infrastructure (mcns, metacrypt, mcr). Single coordination point. | straylight |
|
|
||||||
| **worker** | Runs mcp-agent. Hosts application services. | rift |
|
|
||||||
| **edge** | Runs mcp-agent. Terminates public TLS, forwards to internal services. No application containers. | svc |
|
|
||||||
|
|
||||||
Every node runs an mcp-agent. The master node also runs mcp-master.
|
|
||||||
The master's local agent manages the infrastructure services (mcns,
|
|
||||||
metacrypt, mcr) the same way rift's agent manages application services.
|
|
||||||
|
|
||||||
### mc-proxy Mesh
|
|
||||||
|
|
||||||
Each node runs its own mc-proxy instance. They form a routing mesh:
|
|
||||||
|
|
||||||
```
|
|
||||||
mc-proxy (straylight)
|
|
||||||
├── :443 L7 routes for metacrypt-web, mcr-web
|
|
||||||
├── :8443 L4 passthrough for metacrypt-api, mcr-api
|
|
||||||
└── :9443 L4 passthrough for gRPC services
|
|
||||||
|
|
||||||
mc-proxy (rift)
|
|
||||||
├── :443 L7 routes for internal .svc.mcp hostnames
|
|
||||||
└── :8443 L4/L7 routes for internal APIs
|
|
||||||
|
|
||||||
mc-proxy (svc)
|
|
||||||
└── :443 L7 termination for public hostnames
|
|
||||||
→ forwards to internal .svc.mcp endpoints
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## mcp-master
|
|
||||||
|
|
||||||
The master is a new binary that coordinates cross-node operations. It is
|
|
||||||
**not** a replacement for the agent -- it sits above agents and orchestrates
|
|
||||||
them.
|
|
||||||
|
|
||||||
### Responsibilities
|
|
||||||
|
|
||||||
1. **Accept CLI commands** via gRPC (deploy, undeploy, status, sync).
|
|
||||||
2. **Route deployments** to the correct agent based on the service
|
|
||||||
definition's `node` field.
|
|
||||||
3. **Detect public hostnames** in service definitions and coordinate edge
|
|
||||||
routing with the edge node's agent.
|
|
||||||
4. **Validate public hostnames** against a configured allowlist of domains
|
|
||||||
(e.g., `metacircular.net`, `wntrmute.net`).
|
|
||||||
5. **Resolve edge nodes** by checking DNS CNAME records to determine which
|
|
||||||
node handles public traffic for a given hostname.
|
|
||||||
6. **Coordinate undeploy** across nodes: tear down the service on the
|
|
||||||
worker, then clean up edge routes on the edge node.
|
|
||||||
|
|
||||||
### What the Master Does NOT Do
|
|
||||||
|
|
||||||
- Store container state (agents own their registries).
|
|
||||||
- Manage container lifecycle directly (agents do this).
|
|
||||||
- Run containers (the co-located agent does).
|
|
||||||
- Replace the agent on any node.
|
|
||||||
|
|
||||||
### Master Configuration
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[server]
|
|
||||||
grpc_addr = "100.x.x.x:9555" # master listens on overlay
|
|
||||||
tls_cert = "/srv/mcp-master/certs/cert.pem"
|
|
||||||
tls_key = "/srv/mcp-master/certs/key.pem"
|
|
||||||
|
|
||||||
[mcias]
|
|
||||||
server_url = "https://mcias.metacircular.net:8443"
|
|
||||||
service_name = "mcp-master"
|
|
||||||
|
|
||||||
# Allowed public domains. Hostnames in service definitions must fall
|
|
||||||
# under one of these suffixes.
|
|
||||||
[edge]
|
|
||||||
allowed_domains = ["metacircular.net", "wntrmute.net"]
|
|
||||||
|
|
||||||
# Node registry. The master knows about all nodes.
|
|
||||||
[[nodes]]
|
|
||||||
name = "straylight"
|
|
||||||
address = "100.x.x.x:9444"
|
|
||||||
role = "master"
|
|
||||||
|
|
||||||
[[nodes]]
|
|
||||||
name = "rift"
|
|
||||||
address = "100.95.252.120:9444"
|
|
||||||
role = "worker"
|
|
||||||
|
|
||||||
[[nodes]]
|
|
||||||
name = "svc"
|
|
||||||
address = "100.x.x.x:9444"
|
|
||||||
role = "edge"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Edge Routing
|
|
||||||
|
|
||||||
The core v2 feature: when a service declares a public hostname, the
|
|
||||||
master automatically provisions the edge route.
|
|
||||||
|
|
||||||
### Service Definition
|
|
||||||
|
|
||||||
Public hostnames are declared in the route's `hostname` field. The
|
|
||||||
master distinguishes public from internal hostnames by checking whether
|
|
||||||
they fall under a `.svc.mcp.` subdomain:
|
|
||||||
|
|
||||||
- `mcq.svc.mcp.metacircular.net` → internal (handled by local mc-proxy)
|
|
||||||
- `mcq.metacircular.net` → public (requires edge routing)
|
|
||||||
|
|
||||||
```toml
|
|
||||||
name = "mcq"
|
|
||||||
node = "rift"
|
|
||||||
active = true
|
|
||||||
|
|
||||||
[[components]]
|
|
||||||
name = "mcq"
|
|
||||||
image = "mcr.svc.mcp.metacircular.net:8443/mcq:v0.4.0"
|
|
||||||
volumes = ["/srv/mcq:/srv/mcq"]
|
|
||||||
cmd = ["server", "--config", "/srv/mcq/mcq.toml"]
|
|
||||||
|
|
||||||
# Internal route: handled by rift's mc-proxy.
|
|
||||||
[[components.routes]]
|
|
||||||
name = "internal"
|
|
||||||
port = 8443
|
|
||||||
mode = "l7"
|
|
||||||
|
|
||||||
# Public route: master detects this and sets up edge routing on svc.
|
|
||||||
[[components.routes]]
|
|
||||||
name = "public"
|
|
||||||
port = 8443
|
|
||||||
mode = "l7"
|
|
||||||
hostname = "mcq.metacircular.net"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Deploy Flow with Edge Routing
|
|
||||||
|
|
||||||
When the master receives `Deploy(mcq)`:
|
|
||||||
|
|
||||||
1. **Route to worker**: Master sends `Deploy` RPC to rift's agent with
|
|
||||||
the full service spec. Rift's agent deploys the container and
|
|
||||||
registers mc-proxy routes for all hostnames (both internal and public)
|
|
||||||
on its local mc-proxy.
|
|
||||||
|
|
||||||
2. **Detect public hostnames**: Master inspects the service spec for
|
|
||||||
hostnames that are not `.svc.mcp.` subdomains.
|
|
||||||
|
|
||||||
3. **Validate domains**: Master checks that `mcq.metacircular.net` falls
|
|
||||||
under an allowed domain (`metacircular.net` ✓).
|
|
||||||
|
|
||||||
4. **Resolve edge node**: Master performs a DNS lookup for
|
|
||||||
`mcq.metacircular.net`. If it's a CNAME to `svc.metacircular.net`,
|
|
||||||
the master resolves `svc.metacircular.net` to identify the edge node
|
|
||||||
as `svc`. If DNS is not yet configured (no CNAME), the master uses
|
|
||||||
the default edge node from config.
|
|
||||||
|
|
||||||
5. **Set up edge route**: Master sends an `SetupEdgeRoute` RPC to svc's
|
|
||||||
agent:
|
|
||||||
```
|
|
||||||
SetupEdgeRoute(
|
|
||||||
hostname: "mcq.metacircular.net"
|
|
||||||
backend_hostname: "mcq.svc.mcp.metacircular.net"
|
|
||||||
backend_port: 8443
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
6. **Svc agent provisions**: On receiving `SetupEdgeRoute`, svc's agent:
|
|
||||||
a. Provisions a TLS certificate from Metacrypt for
|
|
||||||
`mcq.metacircular.net`.
|
|
||||||
b. Registers an L7 route in its local mc-proxy:
|
|
||||||
`mcq.metacircular.net:443 → mcq.svc.mcp.metacircular.net:8443`
|
|
||||||
with the provisioned cert.
|
|
||||||
|
|
||||||
7. **Master records the edge route** in its own registry for undeploy
|
|
||||||
cleanup.
|
|
||||||
|
|
||||||
### Undeploy Flow
|
|
||||||
|
|
||||||
When the master receives `Undeploy(mcq)`:
|
|
||||||
|
|
||||||
1. **Look up edge routes**: Master checks its registry for edge routes
|
|
||||||
associated with mcq.
|
|
||||||
2. **Remove edge route**: Master sends `RemoveEdgeRoute(mcq.metacircular.net)`
|
|
||||||
to svc's agent. Svc's agent removes the mc-proxy route and cleans up
|
|
||||||
the cert.
|
|
||||||
3. **Undeploy on worker**: Master sends `Undeploy` RPC to rift's agent.
|
|
||||||
Rift's agent tears down the container, routes, DNS, and certs as in v1.
|
|
||||||
|
|
||||||
### Edge Node DNS Resolution
|
|
||||||
|
|
||||||
The master determines which edge node handles a public hostname by
|
|
||||||
checking DNS:
|
|
||||||
|
|
||||||
1. Look up `mcq.metacircular.net` → CNAME `svc.metacircular.net`
|
|
||||||
2. Look up `svc.metacircular.net` → IP address
|
|
||||||
3. Match the IP against known edge nodes
|
|
||||||
|
|
||||||
If no CNAME exists yet (operator hasn't set it up), the master warns but
|
|
||||||
does not fail. The operator sets up DNS manually at Hurricane Electric.
|
|
||||||
The master can provide a `mcp dns check` command that verifies all public
|
|
||||||
hostnames resolve correctly.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Agent Changes for v2
|
|
||||||
|
|
||||||
### New RPCs
|
|
||||||
|
|
||||||
```protobuf
|
|
||||||
// Edge routing -- called by master on edge nodes.
|
|
||||||
rpc SetupEdgeRoute(SetupEdgeRouteRequest) returns (SetupEdgeRouteResponse);
|
|
||||||
rpc RemoveEdgeRoute(RemoveEdgeRouteRequest) returns (RemoveEdgeRouteResponse);
|
|
||||||
rpc ListEdgeRoutes(ListEdgeRoutesRequest) returns (ListEdgeRoutesResponse);
|
|
||||||
|
|
||||||
message SetupEdgeRouteRequest {
|
|
||||||
string hostname = 1; // public hostname (e.g. "mcq.metacircular.net")
|
|
||||||
string backend_hostname = 2; // internal hostname (e.g. "mcq.svc.mcp.metacircular.net")
|
|
||||||
int32 backend_port = 3; // port on the worker's mc-proxy (e.g. 8443)
|
|
||||||
}
|
|
||||||
|
|
||||||
message SetupEdgeRouteResponse {}
|
|
||||||
|
|
||||||
message RemoveEdgeRouteRequest {
|
|
||||||
string hostname = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message RemoveEdgeRouteResponse {}
|
|
||||||
|
|
||||||
message ListEdgeRoutesRequest {}
|
|
||||||
|
|
||||||
message ListEdgeRoutesResponse {
|
|
||||||
repeated EdgeRoute routes = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message EdgeRoute {
|
|
||||||
string hostname = 1;
|
|
||||||
string backend_hostname = 2;
|
|
||||||
int32 backend_port = 3;
|
|
||||||
string cert_serial = 4;
|
|
||||||
string cert_expires = 5;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### SetupEdgeRoute Implementation
|
|
||||||
|
|
||||||
When the agent receives `SetupEdgeRoute`:
|
|
||||||
|
|
||||||
1. **Resolve backend address**: The agent resolves `backend_hostname` to
|
|
||||||
an IP address (the worker node's overlay IP). It uses the port from
|
|
||||||
the request to form the backend address (e.g., `100.95.252.120:8443`).
|
|
||||||
|
|
||||||
2. **Provision TLS cert**: The agent calls Metacrypt's CA API to issue a
|
|
||||||
certificate for the public hostname. The cert and key are written to
|
|
||||||
the mc-proxy cert directory.
|
|
||||||
|
|
||||||
3. **Register mc-proxy route**: The agent adds an L7 route to its local
|
|
||||||
mc-proxy:
|
|
||||||
- Listener: `:443`
|
|
||||||
- Hostname: `mcq.metacircular.net`
|
|
||||||
- Backend: `100.95.252.120:8443`
|
|
||||||
- Mode: `l7`
|
|
||||||
- TLS cert/key: the provisioned cert
|
|
||||||
- Backend TLS: `true` (worker's mc-proxy serves TLS)
|
|
||||||
|
|
||||||
4. **Record the edge route** in the agent's local registry for listing
|
|
||||||
and cleanup.
|
|
||||||
|
|
||||||
### Cert Provisioning on All Agents
|
|
||||||
|
|
||||||
All agents need Metacrypt configuration to provision certs:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[metacrypt]
|
|
||||||
server_url = "https://metacrypt.svc.mcp.metacircular.net:8443"
|
|
||||||
ca_cert = "/srv/mcp/certs/metacircular-ca.pem"
|
|
||||||
mount = "pki"
|
|
||||||
issuer = "infra"
|
|
||||||
token_path = "/srv/mcp/metacrypt-token"
|
|
||||||
```
|
|
||||||
|
|
||||||
The svc agent provisions certs for public hostnames. The rift agent
|
|
||||||
provisions certs for internal hostnames. Both use the same Metacrypt API.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## CLI Changes for v2
|
|
||||||
|
|
||||||
The CLI's `[[nodes]]` config is replaced by a single master address:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[master]
|
|
||||||
address = "100.x.x.x:9555"
|
|
||||||
|
|
||||||
[mcias]
|
|
||||||
server_url = "https://mcias.metacircular.net:8443"
|
|
||||||
service_name = "mcp"
|
|
||||||
|
|
||||||
[auth]
|
|
||||||
token_path = "/home/kyle/.config/mcp/token"
|
|
||||||
|
|
||||||
[services]
|
|
||||||
dir = "/home/kyle/.config/mcp/services"
|
|
||||||
```
|
|
||||||
|
|
||||||
Commands that currently iterate over nodes (`mcp ps`, `mcp list`,
|
|
||||||
`mcp node list`) instead query the master, which aggregates from all
|
|
||||||
agents.
|
|
||||||
|
|
||||||
Service definition files remain on the operator's workstation. The CLI
|
|
||||||
pushes them to the master on `mcp deploy` and `mcp sync`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Migration Plan
|
|
||||||
|
|
||||||
### Phase 1: Deploy mcp-agent on svc
|
|
||||||
|
|
||||||
svc currently has no mcp-agent. Install and configure one:
|
|
||||||
|
|
||||||
- Create `mcp` user on svc (Debian: `install-agent.sh`)
|
|
||||||
- Install mcp-agent binary
|
|
||||||
- Configure with Metacrypt and mc-proxy socket access
|
|
||||||
- Verify with `mcp node list` (svc shows up)
|
|
||||||
|
|
||||||
### Phase 2: Add edge routing RPCs to agents
|
|
||||||
|
|
||||||
Implement `SetupEdgeRoute`, `RemoveEdgeRoute`, `ListEdgeRoutes` on the
|
|
||||||
agent. Test by calling them directly from the CLI before the master exists.
|
|
||||||
|
|
||||||
### Phase 3: Build mcp-master
|
|
||||||
|
|
||||||
Start with the core coordination loop:
|
|
||||||
|
|
||||||
1. Accept `Deploy` from CLI
|
|
||||||
2. Forward to the correct agent
|
|
||||||
3. Detect public hostnames
|
|
||||||
4. Call `SetupEdgeRoute` on the edge agent
|
|
||||||
|
|
||||||
### Phase 4: Provision straylight
|
|
||||||
|
|
||||||
New node (straylight) takes over as master and hosts core infrastructure:
|
|
||||||
|
|
||||||
1. Deploy mcp-agent on straylight
|
|
||||||
2. Migrate mcns, metacrypt, mcr from rift to straylight
|
|
||||||
3. Deploy mcp-master on straylight
|
|
||||||
4. Update CLI config to point at master
|
|
||||||
|
|
||||||
### Phase 5: Cut over
|
|
||||||
|
|
||||||
- Update DNS to point `*.svc.mcp.metacircular.net` at straylight
|
|
||||||
- Update service definitions to use new node assignments
|
|
||||||
- Verify all services via `mcp ps` and public endpoint tests
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Open Questions
|
|
||||||
|
|
||||||
1. **Master HA**: mcp-master is a single point of failure. For v2, this
|
|
||||||
is acceptable (operator can SSH to agents directly if master is down).
|
|
||||||
v3 could add master replication or make agents self-sufficient for
|
|
||||||
local operations when the master is unreachable.
|
|
||||||
|
|
||||||
2. **Service placement**: v2 still requires explicit `node` assignment
|
|
||||||
in service definitions. Automatic placement based on resource
|
|
||||||
availability is a future concern.
|
|
||||||
|
|
||||||
3. **Cert renewal on edge**: Edge certs have a 90-day TTL. The edge
|
|
||||||
agent needs a renewal loop (similar to the existing `renewWindow`
|
|
||||||
check in `EnsureCert`) or the master needs to periodically re-check
|
|
||||||
edge routes.
|
|
||||||
|
|
||||||
4. **mc-proxy database vs config**: mc-proxy persists routes in SQLite,
|
|
||||||
which can diverge from the TOML config. The agent should be the sole
|
|
||||||
manager of mc-proxy routes via the gRPC admin API, not the TOML file.
|
|
||||||
This avoids the stale-database problem encountered during v1
|
|
||||||
operations on svc.
|
|
||||||
|
|
||||||
5. **straylight hardware**: What hardware is straylight? Does it run
|
|
||||||
NixOS or Debian? Does it use rootless podman like rift?
|
|
||||||
|
|
||||||
6. **Mono-repo for core infrastructure**: The current layout has each
|
|
||||||
service as a separate git repo under `~/src/metacircular/`. A
|
|
||||||
mono-repo for core infrastructure (mcp, mcp-master, mcns, metacrypt,
|
|
||||||
mcr, mc-proxy, mcdsl) would simplify coordinated changes (e.g., a
|
|
||||||
proto change that touches agent + CLI + mc-proxy client), eliminate
|
|
||||||
the `uses_mcdsl` build flag / vendoring, enable a single CI pipeline,
|
|
||||||
and allow atomic platform versioning (one tag per release). Non-core
|
|
||||||
application services (exo, mcq, mcdoc, sgard, kls, mcat) would
|
|
||||||
remain as separate repos with independent release cadences. This is
|
|
||||||
a large migration best tackled after straylight is running and the
|
|
||||||
master exists, when the build/deploy pipeline is already being
|
|
||||||
reorganized.
|
|
||||||
@@ -211,6 +211,7 @@ type ServiceSpec struct {
|
|||||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
Active bool `protobuf:"varint,2,opt,name=active,proto3" json:"active,omitempty"`
|
Active bool `protobuf:"varint,2,opt,name=active,proto3" json:"active,omitempty"`
|
||||||
Components []*ComponentSpec `protobuf:"bytes,3,rep,name=components,proto3" json:"components,omitempty"`
|
Components []*ComponentSpec `protobuf:"bytes,3,rep,name=components,proto3" json:"components,omitempty"`
|
||||||
|
Comment string `protobuf:"bytes,4,opt,name=comment,proto3" json:"comment,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
@@ -266,6 +267,13 @@ func (x *ServiceSpec) GetComponents() []*ComponentSpec {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *ServiceSpec) GetComment() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Comment
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type DeployRequest struct {
|
type DeployRequest struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Service *ServiceSpec `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"`
|
Service *ServiceSpec `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"`
|
||||||
@@ -990,6 +998,7 @@ type ServiceInfo struct {
|
|||||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
Active bool `protobuf:"varint,2,opt,name=active,proto3" json:"active,omitempty"`
|
Active bool `protobuf:"varint,2,opt,name=active,proto3" json:"active,omitempty"`
|
||||||
Components []*ComponentInfo `protobuf:"bytes,3,rep,name=components,proto3" json:"components,omitempty"`
|
Components []*ComponentInfo `protobuf:"bytes,3,rep,name=components,proto3" json:"components,omitempty"`
|
||||||
|
Comment string `protobuf:"bytes,4,opt,name=comment,proto3" json:"comment,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
@@ -1045,6 +1054,13 @@ func (x *ServiceInfo) GetComponents() []*ComponentInfo {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *ServiceInfo) GetComment() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Comment
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type ComponentInfo struct {
|
type ComponentInfo struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
@@ -3048,6 +3064,434 @@ func (*RemoveProxyRouteResponse) Descriptor() ([]byte, []int) {
|
|||||||
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{52}
|
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{52}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SetupEdgeRouteRequest struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"` // public hostname (e.g. "mcq.metacircular.net")
|
||||||
|
BackendHostname string `protobuf:"bytes,2,opt,name=backend_hostname,json=backendHostname,proto3" json:"backend_hostname,omitempty"` // internal .svc.mcp hostname
|
||||||
|
BackendPort int32 `protobuf:"varint,3,opt,name=backend_port,json=backendPort,proto3" json:"backend_port,omitempty"` // port on worker's mc-proxy
|
||||||
|
BackendTls bool `protobuf:"varint,4,opt,name=backend_tls,json=backendTls,proto3" json:"backend_tls,omitempty"` // MUST be true; agent rejects false
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SetupEdgeRouteRequest) Reset() {
|
||||||
|
*x = SetupEdgeRouteRequest{}
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[53]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SetupEdgeRouteRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SetupEdgeRouteRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *SetupEdgeRouteRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[53]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use SetupEdgeRouteRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*SetupEdgeRouteRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{53}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SetupEdgeRouteRequest) GetHostname() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Hostname
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SetupEdgeRouteRequest) GetBackendHostname() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.BackendHostname
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SetupEdgeRouteRequest) GetBackendPort() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.BackendPort
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SetupEdgeRouteRequest) GetBackendTls() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.BackendTls
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetupEdgeRouteResponse struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SetupEdgeRouteResponse) Reset() {
|
||||||
|
*x = SetupEdgeRouteResponse{}
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[54]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SetupEdgeRouteResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SetupEdgeRouteResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *SetupEdgeRouteResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[54]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use SetupEdgeRouteResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*SetupEdgeRouteResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{54}
|
||||||
|
}
|
||||||
|
|
||||||
|
type RemoveEdgeRouteRequest struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RemoveEdgeRouteRequest) Reset() {
|
||||||
|
*x = RemoveEdgeRouteRequest{}
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[55]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RemoveEdgeRouteRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*RemoveEdgeRouteRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *RemoveEdgeRouteRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[55]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use RemoveEdgeRouteRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*RemoveEdgeRouteRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{55}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RemoveEdgeRouteRequest) GetHostname() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Hostname
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type RemoveEdgeRouteResponse struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RemoveEdgeRouteResponse) Reset() {
|
||||||
|
*x = RemoveEdgeRouteResponse{}
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[56]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RemoveEdgeRouteResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*RemoveEdgeRouteResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *RemoveEdgeRouteResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[56]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use RemoveEdgeRouteResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*RemoveEdgeRouteResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{56}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListEdgeRoutesRequest struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListEdgeRoutesRequest) Reset() {
|
||||||
|
*x = ListEdgeRoutesRequest{}
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[57]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListEdgeRoutesRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListEdgeRoutesRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListEdgeRoutesRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[57]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ListEdgeRoutesRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListEdgeRoutesRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{57}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListEdgeRoutesResponse struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Routes []*EdgeRoute `protobuf:"bytes,1,rep,name=routes,proto3" json:"routes,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListEdgeRoutesResponse) Reset() {
|
||||||
|
*x = ListEdgeRoutesResponse{}
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[58]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListEdgeRoutesResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListEdgeRoutesResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListEdgeRoutesResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[58]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ListEdgeRoutesResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListEdgeRoutesResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{58}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListEdgeRoutesResponse) GetRoutes() []*EdgeRoute {
|
||||||
|
if x != nil {
|
||||||
|
return x.Routes
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type EdgeRoute struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"`
|
||||||
|
BackendHostname string `protobuf:"bytes,2,opt,name=backend_hostname,json=backendHostname,proto3" json:"backend_hostname,omitempty"`
|
||||||
|
BackendPort int32 `protobuf:"varint,3,opt,name=backend_port,json=backendPort,proto3" json:"backend_port,omitempty"`
|
||||||
|
CertSerial string `protobuf:"bytes,4,opt,name=cert_serial,json=certSerial,proto3" json:"cert_serial,omitempty"`
|
||||||
|
CertExpires string `protobuf:"bytes,5,opt,name=cert_expires,json=certExpires,proto3" json:"cert_expires,omitempty"` // RFC3339
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EdgeRoute) Reset() {
|
||||||
|
*x = EdgeRoute{}
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[59]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EdgeRoute) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*EdgeRoute) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *EdgeRoute) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[59]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use EdgeRoute.ProtoReflect.Descriptor instead.
|
||||||
|
func (*EdgeRoute) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{59}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EdgeRoute) GetHostname() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Hostname
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EdgeRoute) GetBackendHostname() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.BackendHostname
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EdgeRoute) GetBackendPort() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.BackendPort
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EdgeRoute) GetCertSerial() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.CertSerial
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EdgeRoute) GetCertExpires() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.CertExpires
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type HealthCheckRequest struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HealthCheckRequest) Reset() {
|
||||||
|
*x = HealthCheckRequest{}
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[60]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HealthCheckRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*HealthCheckRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *HealthCheckRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[60]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use HealthCheckRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*HealthCheckRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{60}
|
||||||
|
}
|
||||||
|
|
||||||
|
type HealthCheckResponse struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` // "healthy" or "degraded"
|
||||||
|
Containers int32 `protobuf:"varint,2,opt,name=containers,proto3" json:"containers,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HealthCheckResponse) Reset() {
|
||||||
|
*x = HealthCheckResponse{}
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[61]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HealthCheckResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*HealthCheckResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *HealthCheckResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[61]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use HealthCheckResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*HealthCheckResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{61}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HealthCheckResponse) GetStatus() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Status
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HealthCheckResponse) GetContainers() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Containers
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
var File_proto_mcp_v1_mcp_proto protoreflect.FileDescriptor
|
var File_proto_mcp_v1_mcp_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
const file_proto_mcp_v1_mcp_proto_rawDesc = "" +
|
const file_proto_mcp_v1_mcp_proto_rawDesc = "" +
|
||||||
@@ -3069,13 +3513,14 @@ const file_proto_mcp_v1_mcp_proto_rawDesc = "" +
|
|||||||
"\x03cmd\x18\b \x03(\tR\x03cmd\x12)\n" +
|
"\x03cmd\x18\b \x03(\tR\x03cmd\x12)\n" +
|
||||||
"\x06routes\x18\t \x03(\v2\x11.mcp.v1.RouteSpecR\x06routes\x12\x10\n" +
|
"\x06routes\x18\t \x03(\v2\x11.mcp.v1.RouteSpecR\x06routes\x12\x10\n" +
|
||||||
"\x03env\x18\n" +
|
"\x03env\x18\n" +
|
||||||
" \x03(\tR\x03env\"p\n" +
|
" \x03(\tR\x03env\"\x8a\x01\n" +
|
||||||
"\vServiceSpec\x12\x12\n" +
|
"\vServiceSpec\x12\x12\n" +
|
||||||
"\x04name\x18\x01 \x01(\tR\x04name\x12\x16\n" +
|
"\x04name\x18\x01 \x01(\tR\x04name\x12\x16\n" +
|
||||||
"\x06active\x18\x02 \x01(\bR\x06active\x125\n" +
|
"\x06active\x18\x02 \x01(\bR\x06active\x125\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"components\x18\x03 \x03(\v2\x15.mcp.v1.ComponentSpecR\n" +
|
"components\x18\x03 \x03(\v2\x15.mcp.v1.ComponentSpecR\n" +
|
||||||
"components\"\\\n" +
|
"components\x12\x18\n" +
|
||||||
|
"\acomment\x18\x04 \x01(\tR\acomment\"\\\n" +
|
||||||
"\rDeployRequest\x12-\n" +
|
"\rDeployRequest\x12-\n" +
|
||||||
"\aservice\x18\x01 \x01(\v2\x13.mcp.v1.ServiceSpecR\aservice\x12\x1c\n" +
|
"\aservice\x18\x01 \x01(\v2\x13.mcp.v1.ServiceSpecR\aservice\x12\x1c\n" +
|
||||||
"\tcomponent\x18\x02 \x01(\tR\tcomponent\"C\n" +
|
"\tcomponent\x18\x02 \x01(\tR\tcomponent\"C\n" +
|
||||||
@@ -3112,13 +3557,14 @@ const file_proto_mcp_v1_mcp_proto_rawDesc = "" +
|
|||||||
"\x04name\x18\x01 \x01(\tR\x04name\x12\x18\n" +
|
"\x04name\x18\x01 \x01(\tR\x04name\x12\x18\n" +
|
||||||
"\achanged\x18\x02 \x01(\bR\achanged\x12\x18\n" +
|
"\achanged\x18\x02 \x01(\bR\achanged\x12\x18\n" +
|
||||||
"\asummary\x18\x03 \x01(\tR\asummary\"\x15\n" +
|
"\asummary\x18\x03 \x01(\tR\asummary\"\x15\n" +
|
||||||
"\x13ListServicesRequest\"p\n" +
|
"\x13ListServicesRequest\"\x8a\x01\n" +
|
||||||
"\vServiceInfo\x12\x12\n" +
|
"\vServiceInfo\x12\x12\n" +
|
||||||
"\x04name\x18\x01 \x01(\tR\x04name\x12\x16\n" +
|
"\x04name\x18\x01 \x01(\tR\x04name\x12\x16\n" +
|
||||||
"\x06active\x18\x02 \x01(\bR\x06active\x125\n" +
|
"\x06active\x18\x02 \x01(\bR\x06active\x125\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"components\x18\x03 \x03(\v2\x15.mcp.v1.ComponentInfoR\n" +
|
"components\x18\x03 \x03(\v2\x15.mcp.v1.ComponentInfoR\n" +
|
||||||
"components\"\xd5\x01\n" +
|
"components\x12\x18\n" +
|
||||||
|
"\acomment\x18\x04 \x01(\tR\acomment\"\xd5\x01\n" +
|
||||||
"\rComponentInfo\x12\x12\n" +
|
"\rComponentInfo\x12\x12\n" +
|
||||||
"\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" +
|
"\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" +
|
||||||
"\x05image\x18\x02 \x01(\tR\x05image\x12#\n" +
|
"\x05image\x18\x02 \x01(\tR\x05image\x12#\n" +
|
||||||
@@ -3255,7 +3701,33 @@ const file_proto_mcp_v1_mcp_proto_rawDesc = "" +
|
|||||||
"\x17RemoveProxyRouteRequest\x12#\n" +
|
"\x17RemoveProxyRouteRequest\x12#\n" +
|
||||||
"\rlistener_addr\x18\x01 \x01(\tR\flistenerAddr\x12\x1a\n" +
|
"\rlistener_addr\x18\x01 \x01(\tR\flistenerAddr\x12\x1a\n" +
|
||||||
"\bhostname\x18\x02 \x01(\tR\bhostname\"\x1a\n" +
|
"\bhostname\x18\x02 \x01(\tR\bhostname\"\x1a\n" +
|
||||||
"\x18RemoveProxyRouteResponse2\x92\v\n" +
|
"\x18RemoveProxyRouteResponse\"\xa2\x01\n" +
|
||||||
|
"\x15SetupEdgeRouteRequest\x12\x1a\n" +
|
||||||
|
"\bhostname\x18\x01 \x01(\tR\bhostname\x12)\n" +
|
||||||
|
"\x10backend_hostname\x18\x02 \x01(\tR\x0fbackendHostname\x12!\n" +
|
||||||
|
"\fbackend_port\x18\x03 \x01(\x05R\vbackendPort\x12\x1f\n" +
|
||||||
|
"\vbackend_tls\x18\x04 \x01(\bR\n" +
|
||||||
|
"backendTls\"\x18\n" +
|
||||||
|
"\x16SetupEdgeRouteResponse\"4\n" +
|
||||||
|
"\x16RemoveEdgeRouteRequest\x12\x1a\n" +
|
||||||
|
"\bhostname\x18\x01 \x01(\tR\bhostname\"\x19\n" +
|
||||||
|
"\x17RemoveEdgeRouteResponse\"\x17\n" +
|
||||||
|
"\x15ListEdgeRoutesRequest\"C\n" +
|
||||||
|
"\x16ListEdgeRoutesResponse\x12)\n" +
|
||||||
|
"\x06routes\x18\x01 \x03(\v2\x11.mcp.v1.EdgeRouteR\x06routes\"\xb9\x01\n" +
|
||||||
|
"\tEdgeRoute\x12\x1a\n" +
|
||||||
|
"\bhostname\x18\x01 \x01(\tR\bhostname\x12)\n" +
|
||||||
|
"\x10backend_hostname\x18\x02 \x01(\tR\x0fbackendHostname\x12!\n" +
|
||||||
|
"\fbackend_port\x18\x03 \x01(\x05R\vbackendPort\x12\x1f\n" +
|
||||||
|
"\vcert_serial\x18\x04 \x01(\tR\n" +
|
||||||
|
"certSerial\x12!\n" +
|
||||||
|
"\fcert_expires\x18\x05 \x01(\tR\vcertExpires\"\x14\n" +
|
||||||
|
"\x12HealthCheckRequest\"M\n" +
|
||||||
|
"\x13HealthCheckResponse\x12\x16\n" +
|
||||||
|
"\x06status\x18\x01 \x01(\tR\x06status\x12\x1e\n" +
|
||||||
|
"\n" +
|
||||||
|
"containers\x18\x02 \x01(\x05R\n" +
|
||||||
|
"containers2\xd0\r\n" +
|
||||||
"\x0fMcpAgentService\x127\n" +
|
"\x0fMcpAgentService\x127\n" +
|
||||||
"\x06Deploy\x12\x15.mcp.v1.DeployRequest\x1a\x16.mcp.v1.DeployResponse\x12R\n" +
|
"\x06Deploy\x12\x15.mcp.v1.DeployRequest\x1a\x16.mcp.v1.DeployResponse\x12R\n" +
|
||||||
"\x0fUndeployService\x12\x1e.mcp.v1.UndeployServiceRequest\x1a\x1f.mcp.v1.UndeployServiceResponse\x12F\n" +
|
"\x0fUndeployService\x12\x1e.mcp.v1.UndeployServiceRequest\x1a\x1f.mcp.v1.UndeployServiceResponse\x12F\n" +
|
||||||
@@ -3275,7 +3747,11 @@ const file_proto_mcp_v1_mcp_proto_rawDesc = "" +
|
|||||||
"\x0eListDNSRecords\x12\x1d.mcp.v1.ListDNSRecordsRequest\x1a\x1e.mcp.v1.ListDNSRecordsResponse\x12R\n" +
|
"\x0eListDNSRecords\x12\x1d.mcp.v1.ListDNSRecordsRequest\x1a\x1e.mcp.v1.ListDNSRecordsResponse\x12R\n" +
|
||||||
"\x0fListProxyRoutes\x12\x1e.mcp.v1.ListProxyRoutesRequest\x1a\x1f.mcp.v1.ListProxyRoutesResponse\x12L\n" +
|
"\x0fListProxyRoutes\x12\x1e.mcp.v1.ListProxyRoutesRequest\x1a\x1f.mcp.v1.ListProxyRoutesResponse\x12L\n" +
|
||||||
"\rAddProxyRoute\x12\x1c.mcp.v1.AddProxyRouteRequest\x1a\x1d.mcp.v1.AddProxyRouteResponse\x12U\n" +
|
"\rAddProxyRoute\x12\x1c.mcp.v1.AddProxyRouteRequest\x1a\x1d.mcp.v1.AddProxyRouteResponse\x12U\n" +
|
||||||
"\x10RemoveProxyRoute\x12\x1f.mcp.v1.RemoveProxyRouteRequest\x1a .mcp.v1.RemoveProxyRouteResponse\x123\n" +
|
"\x10RemoveProxyRoute\x12\x1f.mcp.v1.RemoveProxyRouteRequest\x1a .mcp.v1.RemoveProxyRouteResponse\x12O\n" +
|
||||||
|
"\x0eSetupEdgeRoute\x12\x1d.mcp.v1.SetupEdgeRouteRequest\x1a\x1e.mcp.v1.SetupEdgeRouteResponse\x12R\n" +
|
||||||
|
"\x0fRemoveEdgeRoute\x12\x1e.mcp.v1.RemoveEdgeRouteRequest\x1a\x1f.mcp.v1.RemoveEdgeRouteResponse\x12O\n" +
|
||||||
|
"\x0eListEdgeRoutes\x12\x1d.mcp.v1.ListEdgeRoutesRequest\x1a\x1e.mcp.v1.ListEdgeRoutesResponse\x12F\n" +
|
||||||
|
"\vHealthCheck\x12\x1a.mcp.v1.HealthCheckRequest\x1a\x1b.mcp.v1.HealthCheckResponse\x123\n" +
|
||||||
"\x04Logs\x12\x13.mcp.v1.LogsRequest\x1a\x14.mcp.v1.LogsResponse0\x01B*Z(git.wntrmute.dev/mc/mcp/gen/mcp/v1;mcpv1b\x06proto3"
|
"\x04Logs\x12\x13.mcp.v1.LogsRequest\x1a\x14.mcp.v1.LogsResponse0\x01B*Z(git.wntrmute.dev/mc/mcp/gen/mcp/v1;mcpv1b\x06proto3"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -3290,7 +3766,7 @@ func file_proto_mcp_v1_mcp_proto_rawDescGZIP() []byte {
|
|||||||
return file_proto_mcp_v1_mcp_proto_rawDescData
|
return file_proto_mcp_v1_mcp_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_proto_mcp_v1_mcp_proto_msgTypes = make([]protoimpl.MessageInfo, 53)
|
var file_proto_mcp_v1_mcp_proto_msgTypes = make([]protoimpl.MessageInfo, 62)
|
||||||
var file_proto_mcp_v1_mcp_proto_goTypes = []any{
|
var file_proto_mcp_v1_mcp_proto_goTypes = []any{
|
||||||
(*RouteSpec)(nil), // 0: mcp.v1.RouteSpec
|
(*RouteSpec)(nil), // 0: mcp.v1.RouteSpec
|
||||||
(*ComponentSpec)(nil), // 1: mcp.v1.ComponentSpec
|
(*ComponentSpec)(nil), // 1: mcp.v1.ComponentSpec
|
||||||
@@ -3345,7 +3821,16 @@ var file_proto_mcp_v1_mcp_proto_goTypes = []any{
|
|||||||
(*AddProxyRouteResponse)(nil), // 50: mcp.v1.AddProxyRouteResponse
|
(*AddProxyRouteResponse)(nil), // 50: mcp.v1.AddProxyRouteResponse
|
||||||
(*RemoveProxyRouteRequest)(nil), // 51: mcp.v1.RemoveProxyRouteRequest
|
(*RemoveProxyRouteRequest)(nil), // 51: mcp.v1.RemoveProxyRouteRequest
|
||||||
(*RemoveProxyRouteResponse)(nil), // 52: mcp.v1.RemoveProxyRouteResponse
|
(*RemoveProxyRouteResponse)(nil), // 52: mcp.v1.RemoveProxyRouteResponse
|
||||||
(*timestamppb.Timestamp)(nil), // 53: google.protobuf.Timestamp
|
(*SetupEdgeRouteRequest)(nil), // 53: mcp.v1.SetupEdgeRouteRequest
|
||||||
|
(*SetupEdgeRouteResponse)(nil), // 54: mcp.v1.SetupEdgeRouteResponse
|
||||||
|
(*RemoveEdgeRouteRequest)(nil), // 55: mcp.v1.RemoveEdgeRouteRequest
|
||||||
|
(*RemoveEdgeRouteResponse)(nil), // 56: mcp.v1.RemoveEdgeRouteResponse
|
||||||
|
(*ListEdgeRoutesRequest)(nil), // 57: mcp.v1.ListEdgeRoutesRequest
|
||||||
|
(*ListEdgeRoutesResponse)(nil), // 58: mcp.v1.ListEdgeRoutesResponse
|
||||||
|
(*EdgeRoute)(nil), // 59: mcp.v1.EdgeRoute
|
||||||
|
(*HealthCheckRequest)(nil), // 60: mcp.v1.HealthCheckRequest
|
||||||
|
(*HealthCheckResponse)(nil), // 61: mcp.v1.HealthCheckResponse
|
||||||
|
(*timestamppb.Timestamp)(nil), // 62: google.protobuf.Timestamp
|
||||||
}
|
}
|
||||||
var file_proto_mcp_v1_mcp_proto_depIdxs = []int32{
|
var file_proto_mcp_v1_mcp_proto_depIdxs = []int32{
|
||||||
0, // 0: mcp.v1.ComponentSpec.routes:type_name -> mcp.v1.RouteSpec
|
0, // 0: mcp.v1.ComponentSpec.routes:type_name -> mcp.v1.RouteSpec
|
||||||
@@ -3359,64 +3844,73 @@ var file_proto_mcp_v1_mcp_proto_depIdxs = []int32{
|
|||||||
2, // 8: mcp.v1.SyncDesiredStateRequest.services:type_name -> mcp.v1.ServiceSpec
|
2, // 8: mcp.v1.SyncDesiredStateRequest.services:type_name -> mcp.v1.ServiceSpec
|
||||||
16, // 9: mcp.v1.SyncDesiredStateResponse.results:type_name -> mcp.v1.ServiceSyncResult
|
16, // 9: mcp.v1.SyncDesiredStateResponse.results:type_name -> mcp.v1.ServiceSyncResult
|
||||||
19, // 10: mcp.v1.ServiceInfo.components:type_name -> mcp.v1.ComponentInfo
|
19, // 10: mcp.v1.ServiceInfo.components:type_name -> mcp.v1.ComponentInfo
|
||||||
53, // 11: mcp.v1.ComponentInfo.started:type_name -> google.protobuf.Timestamp
|
62, // 11: mcp.v1.ComponentInfo.started:type_name -> google.protobuf.Timestamp
|
||||||
18, // 12: mcp.v1.ListServicesResponse.services:type_name -> mcp.v1.ServiceInfo
|
18, // 12: mcp.v1.ListServicesResponse.services:type_name -> mcp.v1.ServiceInfo
|
||||||
53, // 13: mcp.v1.EventInfo.timestamp:type_name -> google.protobuf.Timestamp
|
62, // 13: mcp.v1.EventInfo.timestamp:type_name -> google.protobuf.Timestamp
|
||||||
18, // 14: mcp.v1.GetServiceStatusResponse.services:type_name -> mcp.v1.ServiceInfo
|
18, // 14: mcp.v1.GetServiceStatusResponse.services:type_name -> mcp.v1.ServiceInfo
|
||||||
22, // 15: mcp.v1.GetServiceStatusResponse.drift:type_name -> mcp.v1.DriftInfo
|
22, // 15: mcp.v1.GetServiceStatusResponse.drift:type_name -> mcp.v1.DriftInfo
|
||||||
23, // 16: mcp.v1.GetServiceStatusResponse.recent_events:type_name -> mcp.v1.EventInfo
|
23, // 16: mcp.v1.GetServiceStatusResponse.recent_events:type_name -> mcp.v1.EventInfo
|
||||||
18, // 17: mcp.v1.LiveCheckResponse.services:type_name -> mcp.v1.ServiceInfo
|
18, // 17: mcp.v1.LiveCheckResponse.services:type_name -> mcp.v1.ServiceInfo
|
||||||
28, // 18: mcp.v1.AdoptContainersResponse.results:type_name -> mcp.v1.AdoptResult
|
28, // 18: mcp.v1.AdoptContainersResponse.results:type_name -> mcp.v1.AdoptResult
|
||||||
53, // 19: mcp.v1.NodeStatusResponse.uptime_since:type_name -> google.protobuf.Timestamp
|
62, // 19: mcp.v1.NodeStatusResponse.uptime_since:type_name -> google.protobuf.Timestamp
|
||||||
38, // 20: mcp.v1.PurgeResponse.results:type_name -> mcp.v1.PurgeResult
|
38, // 20: mcp.v1.PurgeResponse.results:type_name -> mcp.v1.PurgeResult
|
||||||
43, // 21: mcp.v1.DNSZone.records:type_name -> mcp.v1.DNSRecord
|
43, // 21: mcp.v1.DNSZone.records:type_name -> mcp.v1.DNSRecord
|
||||||
42, // 22: mcp.v1.ListDNSRecordsResponse.zones:type_name -> mcp.v1.DNSZone
|
42, // 22: mcp.v1.ListDNSRecordsResponse.zones:type_name -> mcp.v1.DNSZone
|
||||||
46, // 23: mcp.v1.ProxyListenerInfo.routes:type_name -> mcp.v1.ProxyRouteInfo
|
46, // 23: mcp.v1.ProxyListenerInfo.routes:type_name -> mcp.v1.ProxyRouteInfo
|
||||||
53, // 24: mcp.v1.ListProxyRoutesResponse.started_at:type_name -> google.protobuf.Timestamp
|
62, // 24: mcp.v1.ListProxyRoutesResponse.started_at:type_name -> google.protobuf.Timestamp
|
||||||
47, // 25: mcp.v1.ListProxyRoutesResponse.listeners:type_name -> mcp.v1.ProxyListenerInfo
|
47, // 25: mcp.v1.ListProxyRoutesResponse.listeners:type_name -> mcp.v1.ProxyListenerInfo
|
||||||
3, // 26: mcp.v1.McpAgentService.Deploy:input_type -> mcp.v1.DeployRequest
|
59, // 26: mcp.v1.ListEdgeRoutesResponse.routes:type_name -> mcp.v1.EdgeRoute
|
||||||
12, // 27: mcp.v1.McpAgentService.UndeployService:input_type -> mcp.v1.UndeployServiceRequest
|
3, // 27: mcp.v1.McpAgentService.Deploy:input_type -> mcp.v1.DeployRequest
|
||||||
6, // 28: mcp.v1.McpAgentService.StopService:input_type -> mcp.v1.StopServiceRequest
|
12, // 28: mcp.v1.McpAgentService.UndeployService:input_type -> mcp.v1.UndeployServiceRequest
|
||||||
8, // 29: mcp.v1.McpAgentService.StartService:input_type -> mcp.v1.StartServiceRequest
|
6, // 29: mcp.v1.McpAgentService.StopService:input_type -> mcp.v1.StopServiceRequest
|
||||||
10, // 30: mcp.v1.McpAgentService.RestartService:input_type -> mcp.v1.RestartServiceRequest
|
8, // 30: mcp.v1.McpAgentService.StartService:input_type -> mcp.v1.StartServiceRequest
|
||||||
14, // 31: mcp.v1.McpAgentService.SyncDesiredState:input_type -> mcp.v1.SyncDesiredStateRequest
|
10, // 31: mcp.v1.McpAgentService.RestartService:input_type -> mcp.v1.RestartServiceRequest
|
||||||
17, // 32: mcp.v1.McpAgentService.ListServices:input_type -> mcp.v1.ListServicesRequest
|
14, // 32: mcp.v1.McpAgentService.SyncDesiredState:input_type -> mcp.v1.SyncDesiredStateRequest
|
||||||
21, // 33: mcp.v1.McpAgentService.GetServiceStatus:input_type -> mcp.v1.GetServiceStatusRequest
|
17, // 33: mcp.v1.McpAgentService.ListServices:input_type -> mcp.v1.ListServicesRequest
|
||||||
25, // 34: mcp.v1.McpAgentService.LiveCheck:input_type -> mcp.v1.LiveCheckRequest
|
21, // 34: mcp.v1.McpAgentService.GetServiceStatus:input_type -> mcp.v1.GetServiceStatusRequest
|
||||||
27, // 35: mcp.v1.McpAgentService.AdoptContainers:input_type -> mcp.v1.AdoptContainersRequest
|
25, // 35: mcp.v1.McpAgentService.LiveCheck:input_type -> mcp.v1.LiveCheckRequest
|
||||||
36, // 36: mcp.v1.McpAgentService.PurgeComponent:input_type -> mcp.v1.PurgeRequest
|
27, // 36: mcp.v1.McpAgentService.AdoptContainers:input_type -> mcp.v1.AdoptContainersRequest
|
||||||
30, // 37: mcp.v1.McpAgentService.PushFile:input_type -> mcp.v1.PushFileRequest
|
36, // 37: mcp.v1.McpAgentService.PurgeComponent:input_type -> mcp.v1.PurgeRequest
|
||||||
32, // 38: mcp.v1.McpAgentService.PullFile:input_type -> mcp.v1.PullFileRequest
|
30, // 38: mcp.v1.McpAgentService.PushFile:input_type -> mcp.v1.PushFileRequest
|
||||||
34, // 39: mcp.v1.McpAgentService.NodeStatus:input_type -> mcp.v1.NodeStatusRequest
|
32, // 39: mcp.v1.McpAgentService.PullFile:input_type -> mcp.v1.PullFileRequest
|
||||||
41, // 40: mcp.v1.McpAgentService.ListDNSRecords:input_type -> mcp.v1.ListDNSRecordsRequest
|
34, // 40: mcp.v1.McpAgentService.NodeStatus:input_type -> mcp.v1.NodeStatusRequest
|
||||||
45, // 41: mcp.v1.McpAgentService.ListProxyRoutes:input_type -> mcp.v1.ListProxyRoutesRequest
|
41, // 41: mcp.v1.McpAgentService.ListDNSRecords:input_type -> mcp.v1.ListDNSRecordsRequest
|
||||||
49, // 42: mcp.v1.McpAgentService.AddProxyRoute:input_type -> mcp.v1.AddProxyRouteRequest
|
45, // 42: mcp.v1.McpAgentService.ListProxyRoutes:input_type -> mcp.v1.ListProxyRoutesRequest
|
||||||
51, // 43: mcp.v1.McpAgentService.RemoveProxyRoute:input_type -> mcp.v1.RemoveProxyRouteRequest
|
49, // 43: mcp.v1.McpAgentService.AddProxyRoute:input_type -> mcp.v1.AddProxyRouteRequest
|
||||||
39, // 44: mcp.v1.McpAgentService.Logs:input_type -> mcp.v1.LogsRequest
|
51, // 44: mcp.v1.McpAgentService.RemoveProxyRoute:input_type -> mcp.v1.RemoveProxyRouteRequest
|
||||||
4, // 45: mcp.v1.McpAgentService.Deploy:output_type -> mcp.v1.DeployResponse
|
53, // 45: mcp.v1.McpAgentService.SetupEdgeRoute:input_type -> mcp.v1.SetupEdgeRouteRequest
|
||||||
13, // 46: mcp.v1.McpAgentService.UndeployService:output_type -> mcp.v1.UndeployServiceResponse
|
55, // 46: mcp.v1.McpAgentService.RemoveEdgeRoute:input_type -> mcp.v1.RemoveEdgeRouteRequest
|
||||||
7, // 47: mcp.v1.McpAgentService.StopService:output_type -> mcp.v1.StopServiceResponse
|
57, // 47: mcp.v1.McpAgentService.ListEdgeRoutes:input_type -> mcp.v1.ListEdgeRoutesRequest
|
||||||
9, // 48: mcp.v1.McpAgentService.StartService:output_type -> mcp.v1.StartServiceResponse
|
60, // 48: mcp.v1.McpAgentService.HealthCheck:input_type -> mcp.v1.HealthCheckRequest
|
||||||
11, // 49: mcp.v1.McpAgentService.RestartService:output_type -> mcp.v1.RestartServiceResponse
|
39, // 49: mcp.v1.McpAgentService.Logs:input_type -> mcp.v1.LogsRequest
|
||||||
15, // 50: mcp.v1.McpAgentService.SyncDesiredState:output_type -> mcp.v1.SyncDesiredStateResponse
|
4, // 50: mcp.v1.McpAgentService.Deploy:output_type -> mcp.v1.DeployResponse
|
||||||
20, // 51: mcp.v1.McpAgentService.ListServices:output_type -> mcp.v1.ListServicesResponse
|
13, // 51: mcp.v1.McpAgentService.UndeployService:output_type -> mcp.v1.UndeployServiceResponse
|
||||||
24, // 52: mcp.v1.McpAgentService.GetServiceStatus:output_type -> mcp.v1.GetServiceStatusResponse
|
7, // 52: mcp.v1.McpAgentService.StopService:output_type -> mcp.v1.StopServiceResponse
|
||||||
26, // 53: mcp.v1.McpAgentService.LiveCheck:output_type -> mcp.v1.LiveCheckResponse
|
9, // 53: mcp.v1.McpAgentService.StartService:output_type -> mcp.v1.StartServiceResponse
|
||||||
29, // 54: mcp.v1.McpAgentService.AdoptContainers:output_type -> mcp.v1.AdoptContainersResponse
|
11, // 54: mcp.v1.McpAgentService.RestartService:output_type -> mcp.v1.RestartServiceResponse
|
||||||
37, // 55: mcp.v1.McpAgentService.PurgeComponent:output_type -> mcp.v1.PurgeResponse
|
15, // 55: mcp.v1.McpAgentService.SyncDesiredState:output_type -> mcp.v1.SyncDesiredStateResponse
|
||||||
31, // 56: mcp.v1.McpAgentService.PushFile:output_type -> mcp.v1.PushFileResponse
|
20, // 56: mcp.v1.McpAgentService.ListServices:output_type -> mcp.v1.ListServicesResponse
|
||||||
33, // 57: mcp.v1.McpAgentService.PullFile:output_type -> mcp.v1.PullFileResponse
|
24, // 57: mcp.v1.McpAgentService.GetServiceStatus:output_type -> mcp.v1.GetServiceStatusResponse
|
||||||
35, // 58: mcp.v1.McpAgentService.NodeStatus:output_type -> mcp.v1.NodeStatusResponse
|
26, // 58: mcp.v1.McpAgentService.LiveCheck:output_type -> mcp.v1.LiveCheckResponse
|
||||||
44, // 59: mcp.v1.McpAgentService.ListDNSRecords:output_type -> mcp.v1.ListDNSRecordsResponse
|
29, // 59: mcp.v1.McpAgentService.AdoptContainers:output_type -> mcp.v1.AdoptContainersResponse
|
||||||
48, // 60: mcp.v1.McpAgentService.ListProxyRoutes:output_type -> mcp.v1.ListProxyRoutesResponse
|
37, // 60: mcp.v1.McpAgentService.PurgeComponent:output_type -> mcp.v1.PurgeResponse
|
||||||
50, // 61: mcp.v1.McpAgentService.AddProxyRoute:output_type -> mcp.v1.AddProxyRouteResponse
|
31, // 61: mcp.v1.McpAgentService.PushFile:output_type -> mcp.v1.PushFileResponse
|
||||||
52, // 62: mcp.v1.McpAgentService.RemoveProxyRoute:output_type -> mcp.v1.RemoveProxyRouteResponse
|
33, // 62: mcp.v1.McpAgentService.PullFile:output_type -> mcp.v1.PullFileResponse
|
||||||
40, // 63: mcp.v1.McpAgentService.Logs:output_type -> mcp.v1.LogsResponse
|
35, // 63: mcp.v1.McpAgentService.NodeStatus:output_type -> mcp.v1.NodeStatusResponse
|
||||||
45, // [45:64] is the sub-list for method output_type
|
44, // 64: mcp.v1.McpAgentService.ListDNSRecords:output_type -> mcp.v1.ListDNSRecordsResponse
|
||||||
26, // [26:45] is the sub-list for method input_type
|
48, // 65: mcp.v1.McpAgentService.ListProxyRoutes:output_type -> mcp.v1.ListProxyRoutesResponse
|
||||||
26, // [26:26] is the sub-list for extension type_name
|
50, // 66: mcp.v1.McpAgentService.AddProxyRoute:output_type -> mcp.v1.AddProxyRouteResponse
|
||||||
26, // [26:26] is the sub-list for extension extendee
|
52, // 67: mcp.v1.McpAgentService.RemoveProxyRoute:output_type -> mcp.v1.RemoveProxyRouteResponse
|
||||||
0, // [0:26] is the sub-list for field type_name
|
54, // 68: mcp.v1.McpAgentService.SetupEdgeRoute:output_type -> mcp.v1.SetupEdgeRouteResponse
|
||||||
|
56, // 69: mcp.v1.McpAgentService.RemoveEdgeRoute:output_type -> mcp.v1.RemoveEdgeRouteResponse
|
||||||
|
58, // 70: mcp.v1.McpAgentService.ListEdgeRoutes:output_type -> mcp.v1.ListEdgeRoutesResponse
|
||||||
|
61, // 71: mcp.v1.McpAgentService.HealthCheck:output_type -> mcp.v1.HealthCheckResponse
|
||||||
|
40, // 72: mcp.v1.McpAgentService.Logs:output_type -> mcp.v1.LogsResponse
|
||||||
|
50, // [50:73] is the sub-list for method output_type
|
||||||
|
27, // [27:50] is the sub-list for method input_type
|
||||||
|
27, // [27:27] is the sub-list for extension type_name
|
||||||
|
27, // [27:27] is the sub-list for extension extendee
|
||||||
|
0, // [0:27] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_proto_mcp_v1_mcp_proto_init() }
|
func init() { file_proto_mcp_v1_mcp_proto_init() }
|
||||||
@@ -3430,7 +3924,7 @@ func file_proto_mcp_v1_mcp_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_mcp_v1_mcp_proto_rawDesc), len(file_proto_mcp_v1_mcp_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_mcp_v1_mcp_proto_rawDesc), len(file_proto_mcp_v1_mcp_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 53,
|
NumMessages: 62,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ const (
|
|||||||
McpAgentService_ListProxyRoutes_FullMethodName = "/mcp.v1.McpAgentService/ListProxyRoutes"
|
McpAgentService_ListProxyRoutes_FullMethodName = "/mcp.v1.McpAgentService/ListProxyRoutes"
|
||||||
McpAgentService_AddProxyRoute_FullMethodName = "/mcp.v1.McpAgentService/AddProxyRoute"
|
McpAgentService_AddProxyRoute_FullMethodName = "/mcp.v1.McpAgentService/AddProxyRoute"
|
||||||
McpAgentService_RemoveProxyRoute_FullMethodName = "/mcp.v1.McpAgentService/RemoveProxyRoute"
|
McpAgentService_RemoveProxyRoute_FullMethodName = "/mcp.v1.McpAgentService/RemoveProxyRoute"
|
||||||
|
McpAgentService_SetupEdgeRoute_FullMethodName = "/mcp.v1.McpAgentService/SetupEdgeRoute"
|
||||||
|
McpAgentService_RemoveEdgeRoute_FullMethodName = "/mcp.v1.McpAgentService/RemoveEdgeRoute"
|
||||||
|
McpAgentService_ListEdgeRoutes_FullMethodName = "/mcp.v1.McpAgentService/ListEdgeRoutes"
|
||||||
|
McpAgentService_HealthCheck_FullMethodName = "/mcp.v1.McpAgentService/HealthCheck"
|
||||||
McpAgentService_Logs_FullMethodName = "/mcp.v1.McpAgentService/Logs"
|
McpAgentService_Logs_FullMethodName = "/mcp.v1.McpAgentService/Logs"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -71,6 +75,12 @@ type McpAgentServiceClient interface {
|
|||||||
ListProxyRoutes(ctx context.Context, in *ListProxyRoutesRequest, opts ...grpc.CallOption) (*ListProxyRoutesResponse, error)
|
ListProxyRoutes(ctx context.Context, in *ListProxyRoutesRequest, opts ...grpc.CallOption) (*ListProxyRoutesResponse, error)
|
||||||
AddProxyRoute(ctx context.Context, in *AddProxyRouteRequest, opts ...grpc.CallOption) (*AddProxyRouteResponse, error)
|
AddProxyRoute(ctx context.Context, in *AddProxyRouteRequest, opts ...grpc.CallOption) (*AddProxyRouteResponse, error)
|
||||||
RemoveProxyRoute(ctx context.Context, in *RemoveProxyRouteRequest, opts ...grpc.CallOption) (*RemoveProxyRouteResponse, error)
|
RemoveProxyRoute(ctx context.Context, in *RemoveProxyRouteRequest, opts ...grpc.CallOption) (*RemoveProxyRouteResponse, error)
|
||||||
|
// Edge routing (called by master on edge nodes)
|
||||||
|
SetupEdgeRoute(ctx context.Context, in *SetupEdgeRouteRequest, opts ...grpc.CallOption) (*SetupEdgeRouteResponse, error)
|
||||||
|
RemoveEdgeRoute(ctx context.Context, in *RemoveEdgeRouteRequest, opts ...grpc.CallOption) (*RemoveEdgeRouteResponse, error)
|
||||||
|
ListEdgeRoutes(ctx context.Context, in *ListEdgeRoutesRequest, opts ...grpc.CallOption) (*ListEdgeRoutesResponse, error)
|
||||||
|
// Health (called by master on missed heartbeats)
|
||||||
|
HealthCheck(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error)
|
||||||
// Logs
|
// Logs
|
||||||
Logs(ctx context.Context, in *LogsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[LogsResponse], error)
|
Logs(ctx context.Context, in *LogsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[LogsResponse], error)
|
||||||
}
|
}
|
||||||
@@ -263,6 +273,46 @@ func (c *mcpAgentServiceClient) RemoveProxyRoute(ctx context.Context, in *Remove
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *mcpAgentServiceClient) SetupEdgeRoute(ctx context.Context, in *SetupEdgeRouteRequest, opts ...grpc.CallOption) (*SetupEdgeRouteResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(SetupEdgeRouteResponse)
|
||||||
|
err := c.cc.Invoke(ctx, McpAgentService_SetupEdgeRoute_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mcpAgentServiceClient) RemoveEdgeRoute(ctx context.Context, in *RemoveEdgeRouteRequest, opts ...grpc.CallOption) (*RemoveEdgeRouteResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(RemoveEdgeRouteResponse)
|
||||||
|
err := c.cc.Invoke(ctx, McpAgentService_RemoveEdgeRoute_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mcpAgentServiceClient) ListEdgeRoutes(ctx context.Context, in *ListEdgeRoutesRequest, opts ...grpc.CallOption) (*ListEdgeRoutesResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(ListEdgeRoutesResponse)
|
||||||
|
err := c.cc.Invoke(ctx, McpAgentService_ListEdgeRoutes_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mcpAgentServiceClient) HealthCheck(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(HealthCheckResponse)
|
||||||
|
err := c.cc.Invoke(ctx, McpAgentService_HealthCheck_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *mcpAgentServiceClient) Logs(ctx context.Context, in *LogsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[LogsResponse], error) {
|
func (c *mcpAgentServiceClient) Logs(ctx context.Context, in *LogsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[LogsResponse], error) {
|
||||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
stream, err := c.cc.NewStream(ctx, &McpAgentService_ServiceDesc.Streams[0], McpAgentService_Logs_FullMethodName, cOpts...)
|
stream, err := c.cc.NewStream(ctx, &McpAgentService_ServiceDesc.Streams[0], McpAgentService_Logs_FullMethodName, cOpts...)
|
||||||
@@ -313,6 +363,12 @@ type McpAgentServiceServer interface {
|
|||||||
ListProxyRoutes(context.Context, *ListProxyRoutesRequest) (*ListProxyRoutesResponse, error)
|
ListProxyRoutes(context.Context, *ListProxyRoutesRequest) (*ListProxyRoutesResponse, error)
|
||||||
AddProxyRoute(context.Context, *AddProxyRouteRequest) (*AddProxyRouteResponse, error)
|
AddProxyRoute(context.Context, *AddProxyRouteRequest) (*AddProxyRouteResponse, error)
|
||||||
RemoveProxyRoute(context.Context, *RemoveProxyRouteRequest) (*RemoveProxyRouteResponse, error)
|
RemoveProxyRoute(context.Context, *RemoveProxyRouteRequest) (*RemoveProxyRouteResponse, error)
|
||||||
|
// Edge routing (called by master on edge nodes)
|
||||||
|
SetupEdgeRoute(context.Context, *SetupEdgeRouteRequest) (*SetupEdgeRouteResponse, error)
|
||||||
|
RemoveEdgeRoute(context.Context, *RemoveEdgeRouteRequest) (*RemoveEdgeRouteResponse, error)
|
||||||
|
ListEdgeRoutes(context.Context, *ListEdgeRoutesRequest) (*ListEdgeRoutesResponse, error)
|
||||||
|
// Health (called by master on missed heartbeats)
|
||||||
|
HealthCheck(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error)
|
||||||
// Logs
|
// Logs
|
||||||
Logs(*LogsRequest, grpc.ServerStreamingServer[LogsResponse]) error
|
Logs(*LogsRequest, grpc.ServerStreamingServer[LogsResponse]) error
|
||||||
mustEmbedUnimplementedMcpAgentServiceServer()
|
mustEmbedUnimplementedMcpAgentServiceServer()
|
||||||
@@ -379,6 +435,18 @@ func (UnimplementedMcpAgentServiceServer) AddProxyRoute(context.Context, *AddPro
|
|||||||
func (UnimplementedMcpAgentServiceServer) RemoveProxyRoute(context.Context, *RemoveProxyRouteRequest) (*RemoveProxyRouteResponse, error) {
|
func (UnimplementedMcpAgentServiceServer) RemoveProxyRoute(context.Context, *RemoveProxyRouteRequest) (*RemoveProxyRouteResponse, error) {
|
||||||
return nil, status.Error(codes.Unimplemented, "method RemoveProxyRoute not implemented")
|
return nil, status.Error(codes.Unimplemented, "method RemoveProxyRoute not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedMcpAgentServiceServer) SetupEdgeRoute(context.Context, *SetupEdgeRouteRequest) (*SetupEdgeRouteResponse, error) {
|
||||||
|
return nil, status.Error(codes.Unimplemented, "method SetupEdgeRoute not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedMcpAgentServiceServer) RemoveEdgeRoute(context.Context, *RemoveEdgeRouteRequest) (*RemoveEdgeRouteResponse, error) {
|
||||||
|
return nil, status.Error(codes.Unimplemented, "method RemoveEdgeRoute not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedMcpAgentServiceServer) ListEdgeRoutes(context.Context, *ListEdgeRoutesRequest) (*ListEdgeRoutesResponse, error) {
|
||||||
|
return nil, status.Error(codes.Unimplemented, "method ListEdgeRoutes not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedMcpAgentServiceServer) HealthCheck(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) {
|
||||||
|
return nil, status.Error(codes.Unimplemented, "method HealthCheck not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedMcpAgentServiceServer) Logs(*LogsRequest, grpc.ServerStreamingServer[LogsResponse]) error {
|
func (UnimplementedMcpAgentServiceServer) Logs(*LogsRequest, grpc.ServerStreamingServer[LogsResponse]) error {
|
||||||
return status.Error(codes.Unimplemented, "method Logs not implemented")
|
return status.Error(codes.Unimplemented, "method Logs not implemented")
|
||||||
}
|
}
|
||||||
@@ -727,6 +795,78 @@ func _McpAgentService_RemoveProxyRoute_Handler(srv interface{}, ctx context.Cont
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _McpAgentService_SetupEdgeRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(SetupEdgeRouteRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(McpAgentServiceServer).SetupEdgeRoute(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: McpAgentService_SetupEdgeRoute_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(McpAgentServiceServer).SetupEdgeRoute(ctx, req.(*SetupEdgeRouteRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _McpAgentService_RemoveEdgeRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(RemoveEdgeRouteRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(McpAgentServiceServer).RemoveEdgeRoute(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: McpAgentService_RemoveEdgeRoute_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(McpAgentServiceServer).RemoveEdgeRoute(ctx, req.(*RemoveEdgeRouteRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _McpAgentService_ListEdgeRoutes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ListEdgeRoutesRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(McpAgentServiceServer).ListEdgeRoutes(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: McpAgentService_ListEdgeRoutes_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(McpAgentServiceServer).ListEdgeRoutes(ctx, req.(*ListEdgeRoutesRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _McpAgentService_HealthCheck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(HealthCheckRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(McpAgentServiceServer).HealthCheck(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: McpAgentService_HealthCheck_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(McpAgentServiceServer).HealthCheck(ctx, req.(*HealthCheckRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
func _McpAgentService_Logs_Handler(srv interface{}, stream grpc.ServerStream) error {
|
func _McpAgentService_Logs_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||||
m := new(LogsRequest)
|
m := new(LogsRequest)
|
||||||
if err := stream.RecvMsg(m); err != nil {
|
if err := stream.RecvMsg(m); err != nil {
|
||||||
@@ -817,6 +957,22 @@ var McpAgentService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "RemoveProxyRoute",
|
MethodName: "RemoveProxyRoute",
|
||||||
Handler: _McpAgentService_RemoveProxyRoute_Handler,
|
Handler: _McpAgentService_RemoveProxyRoute_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "SetupEdgeRoute",
|
||||||
|
Handler: _McpAgentService_SetupEdgeRoute_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "RemoveEdgeRoute",
|
||||||
|
Handler: _McpAgentService_RemoveEdgeRoute_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "ListEdgeRoutes",
|
||||||
|
Handler: _McpAgentService_ListEdgeRoutes_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "HealthCheck",
|
||||||
|
Handler: _McpAgentService_HealthCheck_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{
|
Streams: []grpc.StreamDesc{
|
||||||
{
|
{
|
||||||
|
|||||||
196
internal/agent/edge_rpc.go
Normal file
196
internal/agent/edge_rpc.go
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
|
||||||
|
mcpv1 "git.wntrmute.dev/mc/mcp/gen/mcp/v1"
|
||||||
|
mcproxy "git.wntrmute.dev/mc/mc-proxy/client/mcproxy"
|
||||||
|
"git.wntrmute.dev/mc/mcp/internal/registry"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetupEdgeRoute provisions a TLS cert and registers an mc-proxy route for a
|
||||||
|
// public hostname. Called by the master on edge nodes.
|
||||||
|
func (a *Agent) SetupEdgeRoute(ctx context.Context, req *mcpv1.SetupEdgeRouteRequest) (*mcpv1.SetupEdgeRouteResponse, error) {
|
||||||
|
a.Logger.Info("SetupEdgeRoute", "hostname", req.GetHostname(),
|
||||||
|
"backend_hostname", req.GetBackendHostname(), "backend_port", req.GetBackendPort())
|
||||||
|
|
||||||
|
// Validate required fields.
|
||||||
|
if req.GetHostname() == "" {
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "hostname is required")
|
||||||
|
}
|
||||||
|
if req.GetBackendHostname() == "" {
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "backend_hostname is required")
|
||||||
|
}
|
||||||
|
if req.GetBackendPort() == 0 {
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "backend_port is required")
|
||||||
|
}
|
||||||
|
if !req.GetBackendTls() {
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "backend_tls must be true")
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.Proxy == nil {
|
||||||
|
return nil, status.Error(codes.FailedPrecondition, "mc-proxy not configured")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve the backend hostname to a Tailnet IP.
|
||||||
|
ips, err := net.LookupHost(req.GetBackendHostname())
|
||||||
|
if err != nil || len(ips) == 0 {
|
||||||
|
return nil, status.Errorf(codes.InvalidArgument, "cannot resolve backend_hostname %q: %v", req.GetBackendHostname(), err)
|
||||||
|
}
|
||||||
|
backendIP := ips[0]
|
||||||
|
|
||||||
|
// Validate the resolved IP is a Tailnet address (100.64.0.0/10).
|
||||||
|
ip := net.ParseIP(backendIP)
|
||||||
|
if ip == nil {
|
||||||
|
return nil, status.Errorf(codes.InvalidArgument, "resolved IP %q is not valid", backendIP)
|
||||||
|
}
|
||||||
|
_, tailnet, _ := net.ParseCIDR("100.64.0.0/10")
|
||||||
|
if !tailnet.Contains(ip) {
|
||||||
|
return nil, status.Errorf(codes.InvalidArgument, "resolved IP %s is not a Tailnet address", backendIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
backend := fmt.Sprintf("%s:%d", backendIP, req.GetBackendPort())
|
||||||
|
|
||||||
|
// Provision TLS cert for the public hostname if cert provisioner is available.
|
||||||
|
certPath := ""
|
||||||
|
keyPath := ""
|
||||||
|
if a.Certs != nil {
|
||||||
|
if err := a.Certs.EnsureCert(ctx, req.GetHostname(), []string{req.GetHostname()}); err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "provision cert for %s: %v", req.GetHostname(), err)
|
||||||
|
}
|
||||||
|
certPath = a.Proxy.CertPath(req.GetHostname())
|
||||||
|
keyPath = a.Proxy.KeyPath(req.GetHostname())
|
||||||
|
} else {
|
||||||
|
// No cert provisioner — check if certs already exist on disk.
|
||||||
|
certPath = a.Proxy.CertPath(req.GetHostname())
|
||||||
|
keyPath = a.Proxy.KeyPath(req.GetHostname())
|
||||||
|
if _, err := os.Stat(certPath); err != nil {
|
||||||
|
return nil, status.Errorf(codes.FailedPrecondition, "no cert provisioner and cert not found at %s", certPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register the L7 route in mc-proxy.
|
||||||
|
route := mcproxy.Route{
|
||||||
|
Hostname: req.GetHostname(),
|
||||||
|
Backend: backend,
|
||||||
|
Mode: "l7",
|
||||||
|
TLSCert: certPath,
|
||||||
|
TLSKey: keyPath,
|
||||||
|
BackendTLS: true,
|
||||||
|
}
|
||||||
|
if err := a.Proxy.AddRoute(ctx, ":443", route); err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "add mc-proxy route: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Persist the edge route in the registry.
|
||||||
|
if err := registry.CreateEdgeRoute(a.DB, req.GetHostname(), req.GetBackendHostname(), int(req.GetBackendPort()), certPath, keyPath); err != nil {
|
||||||
|
a.Logger.Warn("failed to persist edge route", "hostname", req.GetHostname(), "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Logger.Info("edge route established",
|
||||||
|
"hostname", req.GetHostname(), "backend", backend, "cert", certPath)
|
||||||
|
|
||||||
|
return &mcpv1.SetupEdgeRouteResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveEdgeRoute removes an mc-proxy route and cleans up the TLS cert for a
|
||||||
|
// public hostname. Called by the master on edge nodes.
|
||||||
|
func (a *Agent) RemoveEdgeRoute(ctx context.Context, req *mcpv1.RemoveEdgeRouteRequest) (*mcpv1.RemoveEdgeRouteResponse, error) {
|
||||||
|
a.Logger.Info("RemoveEdgeRoute", "hostname", req.GetHostname())
|
||||||
|
|
||||||
|
if req.GetHostname() == "" {
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "hostname is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.Proxy == nil {
|
||||||
|
return nil, status.Error(codes.FailedPrecondition, "mc-proxy not configured")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the mc-proxy route.
|
||||||
|
if err := a.Proxy.RemoveRoute(ctx, ":443", req.GetHostname()); err != nil {
|
||||||
|
a.Logger.Warn("remove mc-proxy route", "hostname", req.GetHostname(), "err", err)
|
||||||
|
// Continue — clean up cert and registry even if route removal fails.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the TLS cert.
|
||||||
|
if a.Certs != nil {
|
||||||
|
if err := a.Certs.RemoveCert(req.GetHostname()); err != nil {
|
||||||
|
a.Logger.Warn("remove cert", "hostname", req.GetHostname(), "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove from registry.
|
||||||
|
if err := registry.DeleteEdgeRoute(a.DB, req.GetHostname()); err != nil {
|
||||||
|
a.Logger.Warn("delete edge route from registry", "hostname", req.GetHostname(), "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Logger.Info("edge route removed", "hostname", req.GetHostname())
|
||||||
|
return &mcpv1.RemoveEdgeRouteResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEdgeRoutes returns all edge routes managed by this agent.
|
||||||
|
func (a *Agent) ListEdgeRoutes(_ context.Context, _ *mcpv1.ListEdgeRoutesRequest) (*mcpv1.ListEdgeRoutesResponse, error) {
|
||||||
|
a.Logger.Debug("ListEdgeRoutes called")
|
||||||
|
|
||||||
|
routes, err := registry.ListEdgeRoutes(a.DB)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "list edge routes: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := &mcpv1.ListEdgeRoutesResponse{}
|
||||||
|
for _, r := range routes {
|
||||||
|
er := &mcpv1.EdgeRoute{
|
||||||
|
Hostname: r.Hostname,
|
||||||
|
BackendHostname: r.BackendHostname,
|
||||||
|
BackendPort: int32(r.BackendPort), //nolint:gosec // port is a small positive integer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read cert metadata if available.
|
||||||
|
if r.TLSCert != "" {
|
||||||
|
if certData, readErr := os.ReadFile(r.TLSCert); readErr == nil { //nolint:gosec // path from registry, not user input
|
||||||
|
if block, _ := pem.Decode(certData); block != nil {
|
||||||
|
if cert, parseErr := x509.ParseCertificate(block.Bytes); parseErr == nil {
|
||||||
|
er.CertSerial = cert.SerialNumber.String()
|
||||||
|
er.CertExpires = cert.NotAfter.UTC().Format(time.RFC3339)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.Routes = append(resp.Routes, er)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HealthCheck returns the agent's health status. Called by the master when
|
||||||
|
// heartbeats are missed.
|
||||||
|
func (a *Agent) HealthCheck(_ context.Context, _ *mcpv1.HealthCheckRequest) (*mcpv1.HealthCheckResponse, error) {
|
||||||
|
a.Logger.Debug("HealthCheck called")
|
||||||
|
|
||||||
|
st := "healthy"
|
||||||
|
containers := int32(0)
|
||||||
|
|
||||||
|
// Count running containers if the runtime is available.
|
||||||
|
if a.Runtime != nil {
|
||||||
|
if list, err := a.Runtime.List(context.Background()); err == nil {
|
||||||
|
containers = int32(len(list)) //nolint:gosec // container count is small
|
||||||
|
} else {
|
||||||
|
st = "degraded"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &mcpv1.HealthCheckResponse{
|
||||||
|
Status: st,
|
||||||
|
Containers: containers,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
@@ -48,6 +48,16 @@ func (p *ProxyRouter) Close() error {
|
|||||||
return p.client.Close()
|
return p.client.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CertPath returns the expected TLS certificate path for a given name.
|
||||||
|
func (p *ProxyRouter) CertPath(name string) string {
|
||||||
|
return filepath.Join(p.certDir, name+".pem")
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyPath returns the expected TLS key path for a given name.
|
||||||
|
func (p *ProxyRouter) KeyPath(name string) string {
|
||||||
|
return filepath.Join(p.certDir, name+".key")
|
||||||
|
}
|
||||||
|
|
||||||
// GetStatus returns the mc-proxy server status.
|
// GetStatus returns the mc-proxy server status.
|
||||||
func (p *ProxyRouter) GetStatus(ctx context.Context) (*mcproxy.Status, error) {
|
func (p *ProxyRouter) GetStatus(ctx context.Context) (*mcproxy.Status, error) {
|
||||||
if p == nil {
|
if p == nil {
|
||||||
|
|||||||
@@ -142,4 +142,18 @@ var migrations = []string{
|
|||||||
FOREIGN KEY (service, component) REFERENCES components(service, name) ON DELETE CASCADE
|
FOREIGN KEY (service, component) REFERENCES components(service, name) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
`,
|
`,
|
||||||
|
|
||||||
|
// Migration 3: service comment
|
||||||
|
`ALTER TABLE services ADD COLUMN comment TEXT NOT NULL DEFAULT '';`,
|
||||||
|
|
||||||
|
// Migration 4: edge routes (v2 — public routes managed by the master)
|
||||||
|
`CREATE TABLE IF NOT EXISTS edge_routes (
|
||||||
|
hostname TEXT NOT NULL PRIMARY KEY,
|
||||||
|
backend_hostname TEXT NOT NULL,
|
||||||
|
backend_port INTEGER NOT NULL,
|
||||||
|
tls_cert TEXT NOT NULL DEFAULT '',
|
||||||
|
tls_key TEXT NOT NULL DEFAULT '',
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);`,
|
||||||
}
|
}
|
||||||
|
|||||||
93
internal/registry/edge_routes.go
Normal file
93
internal/registry/edge_routes.go
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package registry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EdgeRoute represents a public edge route managed by the master.
|
||||||
|
type EdgeRoute struct {
|
||||||
|
Hostname string
|
||||||
|
BackendHostname string
|
||||||
|
BackendPort int
|
||||||
|
TLSCert string
|
||||||
|
TLSKey string
|
||||||
|
CreatedAt time.Time
|
||||||
|
UpdatedAt time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateEdgeRoute inserts or replaces an edge route.
|
||||||
|
func CreateEdgeRoute(db *sql.DB, hostname, backendHostname string, backendPort int, tlsCert, tlsKey string) error {
|
||||||
|
_, err := db.Exec(`
|
||||||
|
INSERT INTO edge_routes (hostname, backend_hostname, backend_port, tls_cert, tls_key, created_at, updated_at)
|
||||||
|
VALUES (?, ?, ?, ?, ?, datetime('now'), datetime('now'))
|
||||||
|
ON CONFLICT(hostname) DO UPDATE SET
|
||||||
|
backend_hostname = excluded.backend_hostname,
|
||||||
|
backend_port = excluded.backend_port,
|
||||||
|
tls_cert = excluded.tls_cert,
|
||||||
|
tls_key = excluded.tls_key,
|
||||||
|
updated_at = datetime('now')
|
||||||
|
`, hostname, backendHostname, backendPort, tlsCert, tlsKey)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create edge route %s: %w", hostname, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEdgeRoute returns a single edge route by hostname.
|
||||||
|
func GetEdgeRoute(db *sql.DB, hostname string) (*EdgeRoute, error) {
|
||||||
|
var r EdgeRoute
|
||||||
|
var createdAt, updatedAt string
|
||||||
|
err := db.QueryRow(`
|
||||||
|
SELECT hostname, backend_hostname, backend_port, tls_cert, tls_key, created_at, updated_at
|
||||||
|
FROM edge_routes WHERE hostname = ?
|
||||||
|
`, hostname).Scan(&r.Hostname, &r.BackendHostname, &r.BackendPort, &r.TLSCert, &r.TLSKey, &createdAt, &updatedAt)
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get edge route %s: %w", hostname, err)
|
||||||
|
}
|
||||||
|
r.CreatedAt, _ = time.Parse("2006-01-02 15:04:05", createdAt)
|
||||||
|
r.UpdatedAt, _ = time.Parse("2006-01-02 15:04:05", updatedAt)
|
||||||
|
return &r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEdgeRoutes returns all edge routes.
|
||||||
|
func ListEdgeRoutes(db *sql.DB) ([]*EdgeRoute, error) {
|
||||||
|
rows, err := db.Query(`
|
||||||
|
SELECT hostname, backend_hostname, backend_port, tls_cert, tls_key, created_at, updated_at
|
||||||
|
FROM edge_routes ORDER BY hostname
|
||||||
|
`)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("list edge routes: %w", err)
|
||||||
|
}
|
||||||
|
defer func() { _ = rows.Close() }()
|
||||||
|
|
||||||
|
var routes []*EdgeRoute
|
||||||
|
for rows.Next() {
|
||||||
|
var r EdgeRoute
|
||||||
|
var createdAt, updatedAt string
|
||||||
|
if err := rows.Scan(&r.Hostname, &r.BackendHostname, &r.BackendPort, &r.TLSCert, &r.TLSKey, &createdAt, &updatedAt); err != nil {
|
||||||
|
return nil, fmt.Errorf("scan edge route: %w", err)
|
||||||
|
}
|
||||||
|
r.CreatedAt, _ = time.Parse("2006-01-02 15:04:05", createdAt)
|
||||||
|
r.UpdatedAt, _ = time.Parse("2006-01-02 15:04:05", updatedAt)
|
||||||
|
routes = append(routes, &r)
|
||||||
|
}
|
||||||
|
return routes, rows.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEdgeRoute removes an edge route by hostname.
|
||||||
|
func DeleteEdgeRoute(db *sql.DB, hostname string) error {
|
||||||
|
result, err := db.Exec(`DELETE FROM edge_routes WHERE hostname = ?`, hostname)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("delete edge route %s: %w", hostname, err)
|
||||||
|
}
|
||||||
|
n, _ := result.RowsAffected()
|
||||||
|
if n == 0 {
|
||||||
|
return fmt.Errorf("edge route %s not found", hostname)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -42,6 +42,14 @@ service McpAgentService {
|
|||||||
rpc AddProxyRoute(AddProxyRouteRequest) returns (AddProxyRouteResponse);
|
rpc AddProxyRoute(AddProxyRouteRequest) returns (AddProxyRouteResponse);
|
||||||
rpc RemoveProxyRoute(RemoveProxyRouteRequest) returns (RemoveProxyRouteResponse);
|
rpc RemoveProxyRoute(RemoveProxyRouteRequest) returns (RemoveProxyRouteResponse);
|
||||||
|
|
||||||
|
// Edge routing (called by master on edge nodes)
|
||||||
|
rpc SetupEdgeRoute(SetupEdgeRouteRequest) returns (SetupEdgeRouteResponse);
|
||||||
|
rpc RemoveEdgeRoute(RemoveEdgeRouteRequest) returns (RemoveEdgeRouteResponse);
|
||||||
|
rpc ListEdgeRoutes(ListEdgeRoutesRequest) returns (ListEdgeRoutesResponse);
|
||||||
|
|
||||||
|
// Health (called by master on missed heartbeats)
|
||||||
|
rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse);
|
||||||
|
|
||||||
// Logs
|
// Logs
|
||||||
rpc Logs(LogsRequest) returns (stream LogsResponse);
|
rpc Logs(LogsRequest) returns (stream LogsResponse);
|
||||||
}
|
}
|
||||||
@@ -72,6 +80,7 @@ message ServiceSpec {
|
|||||||
string name = 1;
|
string name = 1;
|
||||||
bool active = 2;
|
bool active = 2;
|
||||||
repeated ComponentSpec components = 3;
|
repeated ComponentSpec components = 3;
|
||||||
|
string comment = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message DeployRequest {
|
message DeployRequest {
|
||||||
@@ -151,6 +160,7 @@ message ServiceInfo {
|
|||||||
string name = 1;
|
string name = 1;
|
||||||
bool active = 2;
|
bool active = 2;
|
||||||
repeated ComponentInfo components = 3;
|
repeated ComponentInfo components = 3;
|
||||||
|
string comment = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ComponentInfo {
|
message ComponentInfo {
|
||||||
@@ -377,3 +387,43 @@ message RemoveProxyRouteRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message RemoveProxyRouteResponse {}
|
message RemoveProxyRouteResponse {}
|
||||||
|
|
||||||
|
// --- Edge routes (v2) ---
|
||||||
|
|
||||||
|
message SetupEdgeRouteRequest {
|
||||||
|
string hostname = 1; // public hostname (e.g. "mcq.metacircular.net")
|
||||||
|
string backend_hostname = 2; // internal .svc.mcp hostname
|
||||||
|
int32 backend_port = 3; // port on worker's mc-proxy
|
||||||
|
bool backend_tls = 4; // MUST be true; agent rejects false
|
||||||
|
}
|
||||||
|
|
||||||
|
message SetupEdgeRouteResponse {}
|
||||||
|
|
||||||
|
message RemoveEdgeRouteRequest {
|
||||||
|
string hostname = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RemoveEdgeRouteResponse {}
|
||||||
|
|
||||||
|
message ListEdgeRoutesRequest {}
|
||||||
|
|
||||||
|
message ListEdgeRoutesResponse {
|
||||||
|
repeated EdgeRoute routes = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EdgeRoute {
|
||||||
|
string hostname = 1;
|
||||||
|
string backend_hostname = 2;
|
||||||
|
int32 backend_port = 3;
|
||||||
|
string cert_serial = 4;
|
||||||
|
string cert_expires = 5; // RFC3339
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Health check (v2) ---
|
||||||
|
|
||||||
|
message HealthCheckRequest {}
|
||||||
|
|
||||||
|
message HealthCheckResponse {
|
||||||
|
string status = 1; // "healthy" or "degraded"
|
||||||
|
int32 containers = 2;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user