Newer
Older
EnvoyControlPlane / static / index.html
<!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">
            <button onclick="listClusters()">🔁 Reload Clusters</button>
            <button onclick="listListeners()">🔁 Reload Listeners</button>
            <button onclick="loadAllData()">Refresh All Data 🌐</button>
            <button onclick="window.showAddListenerModal()">Add New
                Listener</button>
        </div>

        <h2>Existing Clusters (Click a row for full JSON)</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()">&times;</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()">&times;</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 &rarr; DB)
                    <br> <small>Override DB with Cache (Risk of DB data
                        loss)</small>
                </button>
                <button class="action-button disable"
                    onclick="resolveConsistency('rollback')">
                    Rollback (DB &rarr; 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()">&times;</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 New Listener</h3>
                <span class="close-btn"
                    onclick="hideAddListenerModal()">&times;</span>
            </div>

            <p>Paste the full YAML configuration for the new listener below and
                submit.</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>

    <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>