<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Envoy Configuration Dashboard</title> <link rel="stylesheet" href="style.css"> <script src="https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.min.js"></script> </head> <body> <div class="container"> <h1>Envoy Configuration Dashboard ⚙️</h1> <div id="consistency-status-container"> <button id="consistency-button" class="status-indicator-button" title="System Consistency Status" onclick="showConsistencyModal()" disabled> Loading... </button> </div> <div class="toolbar"> <div class="toolbar-left-group"> <button onclick="listClusters()">🔁 Reload Clusters</button> <button onclick="listListeners()">🔁 Reload Listeners</button> <button onclick="loadAllData()">Refresh All Data 🌐</button> </div> <div class="toolbar-right-group"> <button onclick="window.showAddClusterModal()">Add/Update Cluster</button> <button onclick="window.showAddListenerModal()">Add/Update Listener</button> </div> </div> <div class="utility-links"> <h2>Utility Tools</h2> <p> Need to manually issue a certificate? Use the <a href="/tools/cert_issuer.html" class="link-button">Certificate Issuer Tool 🛡️</a>. </p> </div> <h2>Existing Clusters (Click a row for full JSON/YAML details)</h2> <table id="clusterTable" class="config-table"> <thead> <tr> <th>Cluster Name</th> <th>Status</th> <th>Primary Endpoint</th> <th>Connect Timeout</th> <th>Action</th> </tr> </thead> <tbody id="cluster-table-body"> <tr> <td colspan="4" style="text-align: center;">Loading cluster data...</td> </tr> </tbody> </table> <h2>Existing Listeners (Click a domain/filter for details)</h2> <table id="listenerTable" class="config-table"> <thead> <tr> <th>Listener Name</th> <th>Status</th> <th>Address:Port</th> <th>Domains / Filters</th> <th>Action</th> </tr> </thead> <tbody id="listener-table-body"> <tr> <td colspan="4" style="text-align: center;">Loading listener data...</td> </tr> </tbody> </table> </div> <div id="configModal" class="modal"> <div class="modal-content"> <span class="close" onclick="hideModal()">×</span> <h2 id="modal-title"></h2> <div class="tab-controls"> <button class="tab-button active" data-tab="json">JSON</button> <button class="tab-button" data-tab="yaml">YAML</button> <button id="download-yaml-btn" class="tab-button download-button" onclick="downloadYaml()"> ⬇️ Download YAML </button> </div> <div class="tab-content"> <pre id="modal-json-content" class="code-block"></pre> <pre id="modal-yaml-content" class="code-block" style="display: none;"></pre> </div> </div> </div> <div id="consistencyModal" class="modal" onclick="hideConsistencyModal()"> <div class="modal-content" onclick="event.stopPropagation()"> <div class="modal-header"> <h3>⚠️ Consistency Conflict Detected</h3> <span class="close-btn" onclick="hideConsistencyModal()">×</span> </div> <p>The in-memory cache and the persistent database are out of sync. Please choose a resolution strategy.</p> <h4>Inconsistency Details:</h4> <div id="inconsistency-details-content"> <p><strong>Cache-Only Resources (DB Missing):</strong> <span id="cache-only-count">0</span></p> <pre id="cache-only-data" class="conflict-list"></pre> <p><strong>DB-Only Resources (Cache Missing):</strong> <span id="db-only-count">0</span></p> <pre id="db-only-data" class="conflict-list"></pre> </div> <div class="modal-actions"> <button class="action-button enable" onclick="resolveConsistency('flush')"> Flush (Cache → DB) <br> <small>Override DB with Cache (Risk of DB data loss)</small> </button> <button class="action-button disable" onclick="resolveConsistency('rollback')"> Rollback (DB → Cache) <br> <small>Override Cache with DB (Risk of in-memory data loss)</small> </button> </div> </div> </div> <div id="addFilterChainModal" class="modal"> <div class="modal-content"> <div class="modal-header"> <h3 id="add-fc-modal-title">Add New Filter Chain</h3> <span class="close-btn" onclick="hideAddFilterChainModal()">×</span> </div> <p>Paste the <b>YAML configuration</b> for the new filter chain below. </p> <p> Need help composing a valid configuration? Use the external: <a href="tools/filter_chain.html" target="_blank" class="text-blue-600 hover:text-blue-800 font-medium"> Envoy Filter Chain Composer ↗ </a> </p> <form id="add-filter-chain-form"> <input type="hidden" id="add-fc-listener-name" value=""> <label for="add-fc-yaml-input">Filter Chain YAML:</label> <textarea id="add-fc-yaml-input" rows="15" placeholder="Paste YAML here..."></textarea> <div class="modal-actions"> <button type="button" class="action-button add" onclick="submitNewFilterChain()"> Submit Filter Chain </button> <button type="button" class="action-button disable" onclick="hideAddFilterChainModal()"> Cancel </button> </div> </form> </div> </div> <div id="addListenerModal" class="modal"> <div class="modal-content"> <div class="modal-header"> <h3>Add/Update Listener</h3> <span class="close-btn" onclick="hideAddListenerModal()">×</span> </div> <p>Paste the full <b>YAML configuration</b> for the new listener(s) below and submit. You can provide a single listener object, or a list of listeners under the <code>resources</code> key to load multiple at once:</p> <pre>resources: - <listener 1> - <listener 2></pre> <p>Make sure every listener includes the required type identifier: <code>"@type": type.googleapis.com/envoy.config.listener.v3.Listener</code>, which allows the parser to recognize your configuration. </p> <form id="add-listener-form"> <label for="add-listener-yaml-input">Listener YAML:</label> <textarea id="add-listener-yaml-input" rows="20" placeholder="Paste full listener YAML here..."></textarea> <div class="modal-actions"> <button type="button" class="action-button add" onclick="submitNewListener()"> Submit Listener </button> <button type="button" class="action-button disable" onclick="hideAddListenerModal()"> Cancel </button> </div> </form> </div> </div> <div id="addClusterModal" class="modal"> <div class="modal-content"> <div class="modal-header"> <h3>Add/Update Cluster</h3> <span class="close-btn" onclick="hideAddClusterModal()">×</span> </div> <p>Paste the full <b>YAML configuration</b> for the new cluster(s) below and submit. You can provide a single cluster object, or a list of clusters under the <code>resources</code> key to load multiple at once:</p> <pre>resources: - <cluster 1> - <cluster 2></pre> <p>Or:</p> <pre><cluster 1></pre> <p>Make sure every cluster includes the required type identifier: <code> "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster</code>, which allows the parser to recognize your configuration. </p> <form id="add-cluster-form"> <label for="add-cluster-yaml-input">Cluster YAML:</label> <textarea id="add-cluster-yaml-input" rows="20" placeholder="Paste full cluster YAML here..."></textarea> <div class="modal-actions"> <button type="button" class="action-button add" onclick="submitNewCluster()"> Submit Cluster </button> <button type="button" class="action-button disable" onclick="hideAddClusterModal()"> Cancel </button> </div> </form> </div> </div> <script type="module" src="global.js"></script> <script type="module" src="modals.js"></script> <script type="module" src="data_fetchers.js"></script> <script type="module" src="clusters.js"></script> <script type="module" src="listeners.js"></script> <script type="module" src="consistency.js"></script> <script type="module" src="data_loader.js"></script> </body> </html>