feat: alive UI wave, galaxy presence, spread and fleet enhancements
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Dashboard ambient layer, comrade presence, Mission Deck and War Room, Emberwake supply chain, spread/docs publishing, fleet policy and modules API, CI docker mining, and refreshed USB pack.
This commit is contained in:
@@ -667,6 +667,97 @@ func (f *FleetHandler) BulkDeleteAgents(w http.ResponseWriter, r *http.Request)
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{"success": true, "deleted": deleted})
|
||||
}
|
||||
|
||||
type fleetPolicyRequest struct {
|
||||
AgentIDs []string `json:"agent_ids"`
|
||||
Policy FleetAgentPolicy `json:"policy"`
|
||||
}
|
||||
|
||||
// PutFleetPolicy pushes runtime mining policy to selected online agents.
|
||||
func (f *FleetHandler) PutFleetPolicy(w http.ResponseWriter, r *http.Request) {
|
||||
if f.ws == nil {
|
||||
http.Error(w, "websocket hub unavailable", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
var req fleetPolicyRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, "invalid body", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
policy := normalizeFleetAgentPolicy(req.Policy)
|
||||
if policy.IsEmpty() {
|
||||
http.Error(w, "policy must include at least one field", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
targets := f.ws.ResolveAgentTargets(req.AgentIDs)
|
||||
if len(targets) == 0 {
|
||||
writeJSON(w, map[string]interface{}{
|
||||
"success": false,
|
||||
"error": "no target agents (use agent_ids or \"all\" for online fleet)",
|
||||
})
|
||||
return
|
||||
}
|
||||
pushID := fmt.Sprintf("pol-%d", time.Now().UnixNano())
|
||||
sent, failed := f.ws.PushPolicyUpdate(targets, policy, pushID)
|
||||
writeJSON(w, map[string]interface{}{
|
||||
"success": sent > 0,
|
||||
"sent": sent,
|
||||
"failed": failed,
|
||||
"targets": len(targets),
|
||||
"push_id": pushID,
|
||||
})
|
||||
if f.db != nil {
|
||||
_ = f.db.InsertAudit("", "fleet_policy_push", "", map[string]string{
|
||||
"sent": strconv.Itoa(sent),
|
||||
"mode": policy.MiningMode,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type fleetModulePushRequest struct {
|
||||
AgentIDs []string `json:"agent_ids"`
|
||||
Module string `json:"module"`
|
||||
}
|
||||
|
||||
// PostFleetModulePush tells agents to fetch and apply a signed module pack.
|
||||
func (f *FleetHandler) PostFleetModulePush(w http.ResponseWriter, r *http.Request) {
|
||||
if f.ws == nil {
|
||||
http.Error(w, "websocket hub unavailable", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
var req fleetModulePushRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, "invalid body", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
module := sanitizeModuleName(req.Module)
|
||||
if module == "" {
|
||||
http.Error(w, "module is required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
targets := f.ws.ResolveAgentTargets(req.AgentIDs)
|
||||
if len(targets) == 0 {
|
||||
writeJSON(w, map[string]interface{}{
|
||||
"success": false,
|
||||
"error": "no target agents (use agent_ids or \"all\" for online fleet)",
|
||||
})
|
||||
return
|
||||
}
|
||||
sent, failed := f.ws.PushModuleFetch(targets, module)
|
||||
writeJSON(w, map[string]interface{}{
|
||||
"success": sent > 0,
|
||||
"sent": sent,
|
||||
"failed": failed,
|
||||
"module": module,
|
||||
"targets": len(targets),
|
||||
})
|
||||
if f.db != nil {
|
||||
_ = f.db.InsertAudit("", "fleet_module_push", "", map[string]string{
|
||||
"module": module,
|
||||
"sent": strconv.Itoa(sent),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func mustMarshalFleet(v interface{}) json.RawMessage {
|
||||
b, _ := json.Marshal(v)
|
||||
return b
|
||||
|
||||
Reference in New Issue
Block a user