feat: add cordon/uncordon endpoints and node action toggles

Co-authored-by: aider (openrouter/thinkingmachines/inkling-small:free) <aider@aider.chat>
This commit is contained in:
Jiří Stachandaider committed 2026-10-09 17:32:46 +02:00
1 parent 508cdff893
commit c47bf0ea16
3 files changed
+54

No files matched your search

+10
View File
@@ -115,3 +115,13 @@ def exec_pod(pod: str, namespace: str = "default", context: str = None, containe
cmd += ["--", "sh", "-c", command]
result = run_kubectl(cmd, context=context)
return {"output": result.stdout, "stderr": result.stderr, "returncode": result.returncode}
@app.get("/cordon")
def cordon(node: str, context: str = None):
result = run_kubectl(["cordon", node], context=context)
return {"output": result.stdout, "stderr": result.stderr, "returncode": result.returncode}
@app.get("/uncordon")
def uncordon(node: str, context: str = None):
result = run_kubectl(["uncordon", node], context=context)
return {"output": result.stdout, "stderr": result.stderr, "returncode": result.returncode}
+42
View File
@@ -29,6 +29,15 @@ document.addEventListener('DOMContentLoaded', () => {
if (res) resourceSelect.value = res;
}
function updateActionVisibility() {
const isNode = resourceSelect.value === 'nodes';
document.getElementById('btn-delete').style.display = isNode ? 'none' : 'inline-block';
document.getElementById('btn-logs').style.display = isNode ? 'none' : 'inline-block';
document.getElementById('btn-exec').style.display = isNode ? 'none' : 'inline-block';
document.getElementById('btn-cordon').style.display = isNode ? 'inline-block' : 'none';
document.getElementById('btn-uncordon').style.display = isNode ? 'inline-block' : 'none';
}
async function loadContexts() {
try {
const res = await fetch('http://localhost:8000/contexts');
@@ -112,6 +121,7 @@ document.addEventListener('DOMContentLoaded', () => {
currentData = [];
}
renderList();
updateActionVisibility();
} catch (e) {
console.error('Failed to load resources', e);
resourceList.innerHTML = '<li>Error loading resources</li>';
@@ -253,5 +263,37 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
document.getElementById('btn-cordon').addEventListener('click', async () => {
const node = actionName.value.trim();
if (!node) return;
const ctx = contextSelect.value || null;
try {
const url = new URL('http://localhost:8000/cordon');
url.searchParams.set('node', node);
if (ctx) url.searchParams.set('context', ctx);
const res = await fetch(url);
const data = await res.json();
actionOutput.textContent = data.output || data.error || JSON.stringify(data);
} catch (e) {
actionOutput.textContent = 'Error: ' + e;
}
});
document.getElementById('btn-uncordon').addEventListener('click', async () => {
const node = actionName.value.trim();
if (!node) return;
const ctx = contextSelect.value || null;
try {
const url = new URL('http://localhost:8000/uncordon');
url.searchParams.set('node', node);
if (ctx) url.searchParams.set('context', ctx);
const res = await fetch(url);
const data = await res.json();
actionOutput.textContent = data.output || data.error || JSON.stringify(data);
} catch (e) {
actionOutput.textContent = 'Error: ' + e;
}
});
loadContexts();
});
+2
View File
@@ -52,6 +52,8 @@
<button id="btn-describe">Describe</button>
<button id="btn-logs">Logs</button>
<button id="btn-delete" class="danger">Delete</button>
<button id="btn-cordon" style="display:none;">Cordon</button>
<button id="btn-uncordon" style="display:none;">Uncordon</button>
</div>
<div style="margin-top:0.75rem;">
<label>Exec (non-interactive):</label>