This commit is contained in:
Peter Howell 2025-10-15 23:54:51 +00:00
parent a3093e1c8b
commit 95e00121a3
2 changed files with 169 additions and 131 deletions

View File

@ -30,6 +30,12 @@ const CONTROL_PANEL_STORAGE_KEY = 'label-control-panel-visible';
let diagramConfigOverrides = {};
let initialDiagramConfig = null;
const cssEscape = (window.CSS && typeof window.CSS.escape === 'function')
? window.CSS.escape.bind(window.CSS)
: function(value) {
return String(value).replace(/(["\\\s#.:\[\]\(\)])/g, '\\$1');
};
// Helper to deep-clone the config so we can reset back to defaults later.
function cloneDiagramConfig(obj) {
return JSON.parse(JSON.stringify(obj));
@ -203,11 +209,11 @@ const cy = cytoscape({
'padding': '12px'
}},
{ selector: 'node[type = "sg"]', style: {
'background-color': '#fff7ed',
'border-color': '#f59e0b',
'background-opacity': 0,
'border-width': 0,
'width': 260,
'height': 90,
'padding': '12px'
'height': 32,
'padding': 8
}},
{ selector: 'node[type = "igw"], node[type = "nat"]', style: { 'background-color': '#ffe4e6','border-color': '#fb7185' }},
{ selector: 'edge', style: {
@ -305,12 +311,13 @@ async function loadGraphAndBuildElements(region = 'us-west-1') {
}
// SGs
for (const sg of sgs) {
const name = sg.name || sg.id;
const label = `${name}\n${sg.id}`;
const rin = sg.rules_in || [], rout = sg.rules_out || [];
const label = `${sg.name || sg.id}\ningress: ${(rin[0]||'—')}${rin.length>1?'…':''}`;
const fallbackAcct = vpcAccountMeta.get(sg.vpc || '') || null;
const acctInfo = ensureAccount(sg.accountId || (fallbackAcct && fallbackAcct.id) || null) || fallbackAcct;
const parent = acctInfo ? acctInfo.nodeId : undefined;
elements.push({ data: { id: sg.id, type: 'sg', label, rules: { in: rin, out: rout }, parent, accountId: acctInfo ? acctInfo.id : null, vpc: sg.vpc || null } });
elements.push({ data: { id: sg.id, type: 'sg', label, name, rules: { in: rin, out: rout }, parent, accountId: acctInfo ? acctInfo.id : null, vpc: sg.vpc || null } });
}
// SG<->SG edges based on rules referencing other SGs
function parseSgRef(rule){
@ -351,7 +358,8 @@ async function loadGraphAndBuildElements(region = 'us-west-1') {
// RDS
for (const db of rds) {
const parentSubnet = (db.subnetGroup && db.subnetGroup[0]) || null;
const label = `${db.engine}\n${db.port}\n${db.publiclyAccessible?'public':'private'}`;
const primaryLine = (db.engine || '').split('\n')[0];
const label = primaryLine ? `${db.id}\n${primaryLine}` : db.id;
const fallbackAcct = subnetAccountMeta.get(parentSubnet || '') || null;
const acctInfo = ensureAccount(db.accountId || (fallbackAcct && fallbackAcct.id) || null) || fallbackAcct;
elements.push({ data: { id: db.id, type:'rds', label, engine:db.engine, port:db.port, publiclyAccessible:!!db.publiclyAccessible, parent: parentSubnet, sgs: db.sgs || [], accountId: acctInfo ? acctInfo.id : null } });
@ -449,7 +457,7 @@ async function loadGraphAndBuildElements(region = 'us-west-1') {
const vpnChip=vpnBadge(name); if (vpnChip) badges.push(vpnChip);
const typeChip=typeBadge(type); if (typeChip) badges.push(typeChip);
const badgeHtml=badges.join('');
return `<div class="ncard n-${type}" style="background:none;border:none;box-shadow:none;padding:0;margin:0;display:block;">
return `<div class="ncard n-${type}" data-node-id="${d.id}" style="background:none;border:none;box-shadow:none;padding:0;margin:0;display:block;">
<div class="n-title" style="display:flex;align-items:center;gap:8px;">${iconSvg(type)}${escapeHtml(name)}${badgeHtml}</div>
${lines.join('')}
</div>`;
@ -468,7 +476,7 @@ async function loadGraphAndBuildElements(region = 'us-west-1') {
const typeChip=typeBadge(d.type);
if (typeChip) badges.push(typeChip);
const badgeHtml=badges.join('');
return `<div class="ncard n-${d.type}" style="background:#fee2e2;border:1px solid #ef4444;box-shadow:none;padding:10px 12px;border-radius:10px;">
return `<div class="ncard n-${d.type}" data-node-id="${d.id}" style="background:#fee2e2;border:1px solid #ef4444;box-shadow:none;padding:10px 12px;border-radius:10px;">
<div class="n-title" style="display:flex;align-items:center;gap:8px;">
${icon}
${escapeHtml(name)}${badgeHtml}
@ -486,12 +494,11 @@ async function loadGraphAndBuildElements(region = 'us-west-1') {
const badges=[];
const typeChip=typeBadge('sg'); if (typeChip) badges.push(typeChip);
const badgeHtml=badges.join('');
return `<div class="ncard n-sg" style="background:#fff7ed;border:1px solid #f59e0b;box-shadow:none;padding:10px 12px;border-radius:10px;">
<div class="n-title" style="display:flex;align-items:center;gap:8px;">
${iconSvg('sg')}
${escapeHtml(d.name || d.label || d.id)}${badgeHtml}
return `<div class="ncard n-sg" data-node-id="${d.id}" style="background:#fff7ed;border:1px solid #f59e0b;box-shadow:0 2px 10px rgba(245,158,11,0.25);padding:10px 12px;border-radius:10px;">
<div class="n-title" style="display:flex;align-items:center;gap:8px;font-weight:700;">
${escapeHtml(d.name || d.id)}${badgeHtml}
</div>
<div class="n-sub">${escapeHtml(`${rules} rule${rules===1?'':'s'}`)}</div>
<div class="n-sub">${escapeHtml(d.id)} · ${escapeHtml(`${rules} rule${rules===1?'':'s'}`)}</div>
</div>`;
}
},
@ -505,7 +512,7 @@ async function loadGraphAndBuildElements(region = 'us-west-1') {
const vpnChip=vpnBadge(name); if (vpnChip) badges.push(vpnChip);
const typeChip=typeBadge(d.type); if (typeChip) badges.push(typeChip);
const badgeHtml=badges.join('');
return `<div class="ncard n-${d.type}" style="background:#ffe4e6;border:1px solid #fb7185;box-shadow:none;padding:8px 10px;border-radius:10px;">
return `<div class="ncard n-${d.type}" data-node-id="${d.id}" style="background:#ffe4e6;border:1px solid #fb7185;box-shadow:none;padding:8px 10px;border-radius:10px;">
<div class="n-title" style="display:flex;align-items:center;gap:8px;">
${icon}
${escapeHtml(name)}${badgeHtml}
@ -532,6 +539,7 @@ async function loadGraphAndBuildElements(region = 'us-west-1') {
tpl: function(d){ const name=d.name||(d.label||'').split('\n')[0]||d.id; return `<div class="vpc-big">${escapeHtml(name)}</div>`; }
}
]);
requestAnimationFrame(ensureNodeWidthsFitLabels);
}
// Wrap subnet tabs and reset outer transform so plugin can position parent
@ -602,12 +610,42 @@ async function loadGraphAndBuildElements(region = 'us-west-1') {
});
}
const NODE_MIN_WIDTH = {
alb: 260,
nlb: 260,
ec2: 260,
rds: 260,
sg: 220
};
function ensureNodeWidthsFitLabels(){
const nodes = cy.nodes('[type = "alb"], [type = "nlb"], [type = "ec2"], [type = "rds"], [type = "sg"]');
if (nodes.empty()) return;
const margin = 32;
cy.batch(() => {
nodes.forEach(node => {
const id = node.id();
const labelEl = document.querySelector(`.ncard[data-node-id="${cssEscape(id)}"]`);
if (!labelEl) return;
const rect = labelEl.getBoundingClientRect();
if (!rect || !rect.width) return;
const type = node.data('type');
const minWidth = NODE_MIN_WIDTH[type] || 220;
const desired = Math.max(minWidth, Math.ceil(rect.width) + margin);
if (Math.abs(node.width() - desired) > 1) {
node.style('width', desired);
}
});
});
}
// Re-run every label sizing step so HTML overlays stay in sync with the graph.
function refreshLabelGeometry(){
prepareSubnetTabs();
positionSubnetTabs();
ensureEmptySubnetSizers();
updateEmptySubnetSizerSizes();
requestAnimationFrame(ensureNodeWidthsFitLabels);
}
let renderRefreshScheduled = false;

View File

@ -2,440 +2,440 @@
"nodes": {
"account:acct-shared": {
"position": {
"x": 2383.6718307806645,
"y": 1142.0623550975815
"x": 2005.5164890789051,
"y": 1112.2739169237752
},
"lx": 0,
"ly": 0
},
"account:acct-prod": {
"position": {
"x": -1257.3436368163789,
"y": 1751.2282249012555
"x": -814.0708768306696,
"y": 1653.4126921251755
},
"lx": 0,
"ly": 0
},
"vpc-87832de2": {
"position": {
"x": 2622.379364533625,
"y": 792.8749925626238
"x": 1659.7133575233456,
"y": 513.9754219463099
},
"lx": 77.51854351992131,
"ly": 139.5230395934425
"lx": 73.49444680832619,
"ly": 209.94473204635727
},
"vpc-c84eabad": {
"position": {
"x": -1422.5355956832366,
"y": 280.0140805664038
"x": -47.25,
"y": -18.25
},
"lx": 0,
"ly": 0
},
"vpc-331ad056": {
"position": {
"x": -1435.3398750652455,
"y": 1386.2361491698744
"x": -967.4533224282068,
"y": 907.0632390302223
},
"lx": -134.22057243218103,
"ly": 551.6318031828098
},
"vpc-afe722ca": {
"position": {
"x": -541.0511214212669,
"y": 3010.339213373424
"x": -563.6312192940503,
"y": 2990.9848437681812
},
"lx": 0,
"ly": 0
},
"vpc-03f799f47b766798c": {
"position": {
"x": 2417.1718307806645,
"y": 1690.0755318155339
"x": 1926.2412804626993,
"y": 874.4789294499092
},
"lx": 0,
"ly": 0
},
"subnet-260ee27f": {
"position": {
"x": -1389.5898750652455,
"y": 1215.9751129386946
"x": -1370.4494604541483,
"y": 1184.4611007903993
},
"lx": 0,
"ly": 0
},
"subnet-f73afeae": {
"position": {
"x": -1432.185250998857,
"y": 1941.279260058381
"x": 0,
"y": 0
},
"lx": 0,
"ly": 0
},
"subnet-ebc4188e": {
"position": {
"x": -492.04322569584144,
"y": 2713.2486728912545
"x": -514.6233235686249,
"y": 2693.894303286011
},
"lx": 0,
"ly": 0
},
"subnet-005bfd58e719e031f": {
"position": {
"x": 2795.865315418019,
"y": 521.623811391727
"x": 3237.329690501032,
"y": 365.41687861255815
},
"lx": 0,
"ly": 0
},
"subnet-035f81142068bf961": {
"position": {
"x": 2015.8700930454238,
"y": 1673.9235838762236
"x": 2410.1141180477457,
"y": 1742.7078588998183
},
"lx": 0,
"ly": 0
},
"subnet-d137fd88": {
"position": {
"x": 2876.691988245517,
"y": 1014.8520069370023
"x": 3334.1563633285305,
"y": 855.6631466915302
},
"lx": -95.54884268669878,
"ly": -183.7839139599664
},
"subnet-e98e088c": {
"position": {
"x": -1024.2870646187603,
"y": 1941.0969012227074
"x": -914.4098453851616,
"y": 1819.8764780604447
},
"lx": 0,
"ly": 0
},
"subnet-08e40dcdc103438b8": {
"position": {
"x": 2390.5024469543973,
"y": 1160.3461228120448
"x": 0,
"y": 0
},
"lx": 0,
"ly": 0
},
"subnet-0cb2aa7457413f5fe": {
"position": {
"x": 1937.1896376590757,
"y": 1920.0144292080076
"x": 0,
"y": 0
},
"lx": 0,
"ly": 0
},
"subnet-247a9341": {
"position": {
"x": -1205.4162560440936,
"y": 178.27669594691727
"x": 0,
"y": 0
},
"lx": 0,
"ly": 0
},
"subnet-34173f72": {
"position": {
"x": -1548.6549353223795,
"y": 418.2514651858903
"x": 0,
"y": 0
},
"lx": 0,
"ly": 0
},
"subnet-05b5dcdc91a8d3da2": {
"position": {
"x": 2391.7963891035715,
"y": 963.1972387601206
"x": 0,
"y": 0
},
"lx": -56.280967047329966,
"ly": 12.354358620145604
},
"subnet-16594550": {
"position": {
"x": -496.5590171466923,
"y": 3267.122499752737
"x": -519.1391150194758,
"y": 3247.768130147494
},
"lx": 0,
"ly": 0
},
"subnet-051f6d705e415834d": {
"position": {
"x": 2852.1835304066703,
"y": 1694.1266142274605
"x": 3705.1773007679885,
"y": 1712.2760735536046
},
"lx": 0,
"ly": 0
},
"sg-642cf701": {
"position": {
"x": -128.87428508740095,
"y": 3207.5801320931114
"x": 66.55145954133057,
"y": 3199.7588837084936
},
"lx": 0,
"ly": 0
},
"sg-00600deefd8e47cd0": {
"position": {
"x": 86.73398115413455,
"y": -110.88418680061903
"x": 1748.8526871589222,
"y": 769.1351955087487
},
"lx": 0,
"ly": 0
},
"sg-da75adbf": {
"position": {
"x": 271.174147224467,
"y": 2826.0633311754773
"x": 248.59404935168357,
"y": 2806.708961570234
},
"lx": 0,
"ly": 0
},
"sg-c05a2ba5": {
"position": {
"x": -139.91274956991595,
"y": 23.51131978002694
"x": 1780.7154695082147,
"y": 960.4027949655301
},
"lx": 0,
"ly": 0
},
"sg-0c00315bbb744b876": {
"position": {
"x": 90.45962176444954,
"y": 173.12646633830315
"x": 2005.9176505811133,
"y": 463.7441588404479
},
"lx": 0,
"ly": 0
"lx": 201.20483557975695,
"ly": 251.50604447469595
},
"sg-495ab32c": {
"position": {
"x": 26.527694171634298,
"y": 307.9443846885058
"x": 1735.1781125296234,
"y": 1151.7724351676054
},
"lx": 0,
"ly": 0
},
"sg-0f2465c4421c2d5c2": {
"position": {
"x": 3737.1319279567347,
"y": 1416.6180986742713
"x": 4197.03297815781,
"y": 934.4545348587603
},
"lx": 0,
"ly": 0
},
"sg-8b746aec": {
"position": {
"x": -57.46491042921801,
"y": 798.8332334152173
"x": 1708.0576008049065,
"y": 562.0915192477415
},
"lx": -46.67202145388339,
"ly": 75.49885823422312
},
"sg-0a872ac3a6d9132a6": {
"position": {
"x": 2449.2004574581915,
"y": 2220.1301602993412
"x": 3233.545980714329,
"y": 2324.5478338475505
},
"lx": 0,
"ly": 0
},
"sg-076d2ea1df0054074": {
"position": {
"x": 3020.7762653398454,
"y": 2403.6912205594213
"x": 3394.3395292963014,
"y": 1948.7832081872007
},
"lx": 0,
"ly": 0
},
"sg-b45a2bd1": {
"position": {
"x": 3732.2813094098105,
"y": 823.5446930393971
"x": 4049.2497015379804,
"y": 665.4137035511877
},
"lx": 0,
"ly": 0
},
"sg-4235ee27": {
"position": {
"x": 134.85579854853708,
"y": 3695.499049118454
"x": 471.4854636272555,
"y": 3322.697640031519
},
"lx": 0,
"ly": 0
},
"sg-04167d2e18ba15e45": {
"position": {
"x": 2115.6486154236227,
"y": 2405.8871924989144
"x": 3195.468001006085,
"y": 2109.5037824422498
},
"lx": 0,
"ly": 0
},
"sg-06348763": {
"position": {
"x": -770.8920039501696,
"y": 953.8441924471215
"x": -385.8437743498514,
"y": 801.5675421441275
},
"lx": 0,
"ly": 0
},
"sg-08fb4b412f90d5913": {
"position": {
"x": -729.2224680353501,
"y": 1385.8819086010787
"x": -430.38365938247586,
"y": 1413.7977731519345
},
"lx": 0,
"ly": 0
},
"sg-09621eafa81d9554d": {
"position": {
"x": 3699.811020652474,
"y": 413.5355291862605
"x": 4048.701400244682,
"y": 269.85723972518815
},
"lx": 0,
"ly": 0
},
"i-0dc281f8d162602c8": {
"position": {
"x": -1670.173475504735,
"y": 1265.2737998613272
"x": -1643.4066448564133,
"y": 1212.155742320591
},
"lx": 0,
"ly": 0
},
"i-0997a73b08f6e5862": {
"position": {
"x": -437.8090171466923,
"y": 3214.5652456498806
"x": -460.38911501947575,
"y": 3195.210876044637
},
"lx": 0,
"ly": 0
},
"i-0c8100e3460fa8fd0": {
"position": {
"x": -998.7591067002047,
"y": 1582.324828760348
"x": -971.992276051883,
"y": 1529.2067712196117
},
"lx": 0,
"ly": 0
},
"i-041021cd89e15282c": {
"position": {
"x": -432.29322569584144,
"y": 2737.4986728912545
"x": -454.87332356862487,
"y": 2718.144303286011
},
"lx": 0,
"ly": 0
},
"i-073b97cbda2b200c3": {
"position": {
"x": 2873.640669480026,
"y": 873.0643097359127
"x": 3331.10504456304,
"y": 713.8754494904406
},
"lx": 0,
"ly": 0
},
"i-0669f35ab2d0fc444": {
"position": {
"x": 2871.2248620457804,
"y": 1046.458986548435
"x": 3328.689237128793,
"y": 887.2701263029628
},
"lx": 0,
"ly": 0
},
"i-01b3f3cd57976bdf3": {
"position": {
"x": 2999.2433070110083,
"y": 1205.139704138092
"x": 3456.707682094021,
"y": 1045.9508438926198
},
"lx": 0,
"ly": 0
},
"i-0272763b46610ac1b": {
"position": {
"x": -1672.5138621287765,
"y": 948.3290971162517
"x": -1645.7470314804548,
"y": 895.2110395755153
},
"lx": 238.46757499625102,
"ly": -50.2036999992107
},
"i-0c82adf476c7c5e32": {
"position": {
"x": -1662.0472894085924,
"y": 1105.0564398606823
"x": -1635.2804587602707,
"y": 1051.938382319946
},
"lx": 0,
"ly": 0
},
"i-0636fd0b033c9b32a": {
"position": {
"x": -983.5062746257561,
"y": 1393.6706243649835
"x": -1327.719116265829,
"y": 1572.414862004494
},
"lx": 0,
"ly": 0
},
"i-09241599c2590b66a": {
"position": {
"x": -1023.8550722894502,
"y": 981.8165353124757
"x": -1409.5590614880932,
"y": 1392.4230681322329
},
"lx": 0,
"ly": 0
},
"i-0d7f643cb9d960645": {
"position": {
"x": 2801.1434922974354,
"y": 1561.6366344230603
"x": 3927.4825609253985,
"y": 1714.8122689424063
},
"lx": 0,
"ly": 0
},
"i-082b27477bbe6d8b5": {
"position": {
"x": 2077.620093045424,
"y": 1698.1735838762236
"x": 2471.8641180477457,
"y": 1766.9578588998183
},
"lx": 0,
"ly": 0
},
"f8-db-01": {
"position": {
"x": -986.5370646187603,
"y": 1959.3469012227074
"x": -876.6598453851616,
"y": 1832.1264780604447
},
"lx": 0,
"ly": 0
},
"logon-db-02": {
"position": {
"x": -439.8721002904598,
"y": 3368.179753855594
"x": -462.4521981632432,
"y": 3348.8253842503505
},
"lx": 0,
"ly": 0
},
"vault-db-production-v2": {
"position": {
"x": 2832.5476223232313,
"y": 453.61028098715565
"x": 3290.0119974062445,
"y": 294.42142074168316
},
"lx": 0,
"ly": 0
"lx": 134.807239838437,
"ly": -6.036145067392795
},
"vault-db-staging-v2": {
"position": {
"x": 2830.6830085128063,
"y": 626.1373417962984
"x": 3288.1473835958195,
"y": 466.94848155082593
},
"lx": 0,
"ly": 0
},
"NodeAppALB": {
"position": {
"x": 3026.2235685159053,
"y": 1874.6165940318608
"x": 3572.372040610579,
"y": 1757.739878164803
},
"lx": 0,
"ly": 0