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:
1 parent
508cdff893
commit
c47bf0ea16
3 files changed
+54
No files matched your search
@@ -115,3 +115,13 @@ def exec_pod(pod: str, namespace: str = "default", context: str = None, containe
|
|||||||
cmd += ["--", "sh", "-c", command]
|
cmd += ["--", "sh", "-c", command]
|
||||||
result = run_kubectl(cmd, context=context)
|
result = run_kubectl(cmd, context=context)
|
||||||
return {"output": result.stdout, "stderr": result.stderr, "returncode": result.returncode}
|
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}
|
||||||
@@ -29,6 +29,15 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
if (res) resourceSelect.value = res;
|
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() {
|
async function loadContexts() {
|
||||||
try {
|
try {
|
||||||
const res = await fetch('http://localhost:8000/contexts');
|
const res = await fetch('http://localhost:8000/contexts');
|
||||||
@@ -112,6 +121,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
currentData = [];
|
currentData = [];
|
||||||
}
|
}
|
||||||
renderList();
|
renderList();
|
||||||
|
updateActionVisibility();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to load resources', e);
|
console.error('Failed to load resources', e);
|
||||||
resourceList.innerHTML = '<li>Error loading resources</li>';
|
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();
|
loadContexts();
|
||||||
});
|
});
|
||||||
@@ -52,6 +52,8 @@
|
|||||||
<button id="btn-describe">Describe</button>
|
<button id="btn-describe">Describe</button>
|
||||||
<button id="btn-logs">Logs</button>
|
<button id="btn-logs">Logs</button>
|
||||||
<button id="btn-delete" class="danger">Delete</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>
|
||||||
<div style="margin-top:0.75rem;">
|
<div style="margin-top:0.75rem;">
|
||||||
<label>Exec (non-interactive):</label>
|
<label>Exec (non-interactive):</label>
|
||||||
|
|||||||
Reference in new issue
Block a user