import unittest from backend.agent_tools import ( classify_agent_command, classify_kubectl_command, classify_shell_command, parse_kubectl_command, parse_shell_command, ) class KubectlCommandPolicyTest(unittest.TestCase): def test_allows_read_only_kubectl_command_for_autonomous_execution(self): decision = classify_kubectl_command("kubectl get pods -n production -o wide") self.assertEqual(decision.mode, "read") self.assertFalse(decision.requires_approval) def test_requires_approval_for_mutating_kubectl_command(self): decision = classify_kubectl_command("kubectl rollout restart deployment/api -n production") self.assertEqual(decision.mode, "write") self.assertTrue(decision.requires_approval) def test_rejects_shell_operators_and_non_kubectl_commands(self): for command in ( "kubectl get pods; rm -rf /", "kubectl get pods | sh", "bash -c kubectl get pods", "sudo kubectl get pods", ): with self.subTest(command=command): with self.assertRaises(ValueError): parse_kubectl_command(command) def test_rejects_exec_even_when_command_looks_read_only(self): decision = classify_kubectl_command("kubectl exec api-0 -- cat /etc/hosts") self.assertEqual(decision.mode, "write") self.assertTrue(decision.requires_approval) class ShellCommandPolicyTest(unittest.TestCase): def test_allows_read_only_systemctl_status_for_autonomous_execution(self): decision = classify_shell_command("systemctl status kubelet") self.assertEqual(decision.mode, "read") self.assertFalse(decision.requires_approval) def test_allows_journalctl_with_flags(self): decision = classify_shell_command("journalctl -u kubelet -n 100 --no-pager") self.assertEqual(decision.mode, "read") self.assertFalse(decision.requires_approval) def test_allows_crictl_ps(self): decision = classify_shell_command("crictl ps -a") self.assertEqual(decision.mode, "read") self.assertFalse(decision.requires_approval) def test_allows_df_and_free(self): for command in ("df -h", "free -m", "uptime"): with self.subTest(command=command): decision = classify_shell_command(command) self.assertEqual(decision.mode, "read") self.assertFalse(decision.requires_approval) def test_allows_ip_addr(self): decision = classify_shell_command("ip addr show") self.assertEqual(decision.mode, "read") self.assertFalse(decision.requires_approval) def test_requires_approval_for_systemctl_restart(self): decision = classify_shell_command("systemctl restart kubelet") self.assertEqual(decision.mode, "write") self.assertTrue(decision.requires_approval) def test_rejects_unknown_binary(self): with self.assertRaises(ValueError): classify_shell_command("rm -rf /") def test_rejects_shell_operators_in_shell_command(self): for command in ( "systemctl status kubelet; rm -rf /", "df -h | grep vda", "journalctl -u kubelet > /tmp/log", ): with self.subTest(command=command): with self.assertRaises(ValueError): parse_shell_command(command) def test_cat_only_allows_safe_paths(self): decision = classify_shell_command("cat /etc/os-release") self.assertEqual(decision.mode, "read") self.assertFalse(decision.requires_approval) def test_cat_rejects_unsafe_path(self): with self.assertRaises(ValueError): classify_shell_command("cat /etc/shadow") class AgentCommandDispatchTest(unittest.TestCase): def test_dispatches_kubectl_command_to_kubectl_classifier(self): decision = classify_agent_command("kubectl get pods -A") self.assertEqual(decision.mode, "read") self.assertEqual(decision.verb, "get") def test_dispatches_shell_command_to_shell_classifier(self): decision = classify_agent_command("systemctl status kubelet") self.assertEqual(decision.mode, "read") self.assertEqual(decision.verb, "systemctl") def test_dispatches_write_shell_command_to_shell_classifier(self): decision = classify_agent_command("systemctl restart kubelet") self.assertEqual(decision.mode, "write") self.assertTrue(decision.requires_approval) def test_dispatches_write_kubectl_command(self): decision = classify_agent_command("kubectl delete pod api-0 -n prod") self.assertEqual(decision.mode, "write") self.assertTrue(decision.requires_approval) if __name__ == "__main__": unittest.main()