diff --git a/controller/overview.go b/controller/overview.go index 72870826..5c3bb6f8 100644 --- a/controller/overview.go +++ b/controller/overview.go @@ -38,16 +38,6 @@ func (h *overviewHandler) Handle(_ metadata.OverviewParams, principal *rest_mode } ovr := &rest_model_zrok.Overview{AccountLimited: accountLimited} for _, env := range envs { - shrs, err := str.FindSharesForEnvironment(env.Id, trx) - if err != nil { - logrus.Errorf("error finding shares for environment '%v': %v", env.ZId, err) - return metadata.NewOverviewInternalServerError() - } - slm, err := newSharesLimitedMap(shrs, trx) - if err != nil { - logrus.Errorf("error finding limited shares for environment '%v': %v", env.ZId, err) - return metadata.NewOverviewInternalServerError() - } envRes := &rest_model_zrok.EnvironmentAndResources{ Environment: &rest_model_zrok.Environment{ Address: env.Address, @@ -59,6 +49,16 @@ func (h *overviewHandler) Handle(_ metadata.OverviewParams, principal *rest_mode UpdatedAt: env.UpdatedAt.UnixMilli(), }, } + shrs, err := str.FindSharesForEnvironment(env.Id, trx) + if err != nil { + logrus.Errorf("error finding shares for environment '%v': %v", env.ZId, err) + return metadata.NewOverviewInternalServerError() + } + slm, err := newSharesLimitedMap(shrs, trx) + if err != nil { + logrus.Errorf("error finding limited shares for environment '%v': %v", env.ZId, err) + return metadata.NewOverviewInternalServerError() + } for _, shr := range shrs { feEndpoint := "" if shr.FrontendEndpoint != nil { @@ -87,6 +87,28 @@ func (h *overviewHandler) Handle(_ metadata.OverviewParams, principal *rest_mode } envRes.Shares = append(envRes.Shares, envShr) } + fes, err := str.FindFrontendsForEnvironment(env.Id, trx) + if err != nil { + logrus.Errorf("error finding frontends for environment '%v': %v", env.ZId, err) + return metadata.NewOverviewInternalServerError() + } + for _, fe := range fes { + envFe := &rest_model_zrok.Frontend{ + ID: int64(fe.Id), + ZID: fe.ZId, + CreatedAt: fe.CreatedAt.UnixMilli(), + UpdatedAt: fe.UpdatedAt.UnixMilli(), + } + if fe.PrivateShareId != nil { + feShr, err := str.GetShare(*fe.PrivateShareId, trx) + if err != nil { + logrus.Errorf("error getting share for frontend '%v': %v", fe.ZId, err) + return metadata.NewOverviewInternalServerError() + } + envFe.ShrToken = feShr.Token + } + envRes.Frontends = append(envRes.Frontends, envFe) + } ovr.Environments = append(ovr.Environments, envRes) } return metadata.NewOverviewOK().WithPayload(ovr) diff --git a/rest_model_zrok/frontend.go b/rest_model_zrok/frontend.go index 65cc237d..3185dcaf 100644 --- a/rest_model_zrok/frontend.go +++ b/rest_model_zrok/frontend.go @@ -20,6 +20,9 @@ type Frontend struct { // created at CreatedAt int64 `json:"createdAt,omitempty"` + // id + ID int64 `json:"id,omitempty"` + // shr token ShrToken string `json:"shrToken,omitempty"` diff --git a/rest_server_zrok/embedded_spec.go b/rest_server_zrok/embedded_spec.go index 0ac1aecc..40dd52ea 100644 --- a/rest_server_zrok/embedded_spec.go +++ b/rest_server_zrok/embedded_spec.go @@ -1144,6 +1144,9 @@ func init() { "createdAt": { "type": "integer" }, + "id": { + "type": "integer" + }, "shrToken": { "type": "string" }, @@ -2655,6 +2658,9 @@ func init() { "createdAt": { "type": "integer" }, + "id": { + "type": "integer" + }, "shrToken": { "type": "string" }, diff --git a/specs/zrok.yml b/specs/zrok.yml index c8f4e458..bf0ce90f 100644 --- a/specs/zrok.yml +++ b/specs/zrok.yml @@ -734,6 +734,8 @@ definitions: frontend: type: object properties: + id: + type: integer shrToken: type: string zId: diff --git a/ui/src/api/types.js b/ui/src/api/types.js index ae81ebab..b55e3d00 100644 --- a/ui/src/api/types.js +++ b/ui/src/api/types.js @@ -106,6 +106,7 @@ * @typedef frontend * @memberof module:types * + * @property {number} id * @property {string} shrToken * @property {string} zId * @property {number} createdAt diff --git a/ui/src/console/visualizer/Network.js b/ui/src/console/visualizer/Network.js index 86858266..2206a185 100644 --- a/ui/src/console/visualizer/Network.js +++ b/ui/src/console/visualizer/Network.js @@ -3,10 +3,11 @@ import {useEffect, useRef} from "react"; import {ForceGraph2D} from "react-force-graph"; import * as d3 from "d3-force-3d"; import {roundRect} from "./draw"; -import {mdiShareVariant, mdiConsole, mdiAccount, mdiAlertOctagram} from "@mdi/js"; +import {mdiShareVariant, mdiConsole, mdiAccount, mdiAlertOctagram, mdiAccessPointNetwork} from "@mdi/js"; const accountIcon = new Path2D(mdiAccount); const environmentIcon = new Path2D(mdiConsole); +const frontendIcon = new Path2D(mdiAccessPointNetwork); const limitIcon = new Path2D(mdiAlertOctagram); const shareIcon = new Path2D(mdiShareVariant); @@ -46,6 +47,9 @@ const Network = (props) => { case "environment": nodeIcon.addPath(environmentIcon, xform); break; + case "frontend": + nodeIcon.addPath(frontendIcon, xform); + break; case "account": nodeIcon.addPath(accountIcon, xform); break; @@ -84,7 +88,8 @@ const Network = (props) => { height={800} onNodeClick={nodeClicked} linkOpacity={.75} - linkWidth={1.5} + linkWidth={(l) => l.type === "data" ? 3.0 : 1.5 } + linkLineDash={(l) => l.type === "data" ? [3, 3] : [] } nodeCanvasObject={paintNode} backgroundColor={"linear-gradient(180deg, #0E0238 0%, #231069 100%);"} cooldownTicks={300} diff --git a/ui/src/console/visualizer/graph.js b/ui/src/console/visualizer/graph.js index 92625c89..afbd1e82 100644 --- a/ui/src/console/visualizer/graph.js +++ b/ui/src/console/visualizer/graph.js @@ -31,6 +31,8 @@ export const mergeGraph = (oldGraph, user, accountLimited, newOverview) => { newGraph.nodes.push(accountNode); if(newOverview) { + let allShares = {}; + let allFrontends = []; newOverview.forEach(env => { let limited = !!env.limited; let envNode = { @@ -60,6 +62,7 @@ export const mergeGraph = (oldGraph, user, accountLimited, newOverview) => { limited: !!shr.limited || envNode.limited, val: 50 }; + allShares[shr.token] = shrNode; newGraph.nodes.push(shrNode); newGraph.links.push({ target: envNode.id, @@ -68,6 +71,35 @@ export const mergeGraph = (oldGraph, user, accountLimited, newOverview) => { }); }); } + if(env.frontends) { + env.frontends.forEach(fe => { + let feNode = { + id: fe.id, + target: fe.shrToken, + label: fe.shrToken, + type: "frontend", + val: 50 + } + allFrontends.push(feNode); + newGraph.nodes.push(feNode); + newGraph.links.push({ + target: envNode.id, + source: feNode.id, + color: "#04adef" + }); + }); + } + }); + allFrontends.forEach(fe => { + let target = allShares[fe.target]; + if(target) { + newGraph.links.push({ + target: target.id, + source: fe.id, + color: "#9BF316", + type: "data", + }); + } }); } newGraph.nodes = sortNodes(newGraph.nodes);