Fixed Breaking Legacy change
This commit is contained in:
+26
-39
@@ -20,6 +20,7 @@ from textual.widgets import (
|
||||
|
||||
from flows.otp import otp_activities_by_agent, otp_revoke
|
||||
from flows.prepPolicy import menu_policy_enforce
|
||||
from flows.quietAgent import findQuietAgents
|
||||
from models.agent import Agent
|
||||
from models.policy import Policy
|
||||
from screens.moveagentworkflowscreen import MoveAgentWorkflowScreen
|
||||
@@ -325,6 +326,8 @@ class MainMenuScreen(Screen):
|
||||
self.app.push_screen(OTPWorkflowScreen(self.app.devices))
|
||||
event.stop()
|
||||
return # Don't exit the app
|
||||
case "find_quiet_button":
|
||||
_PENDING_JOB = ("legacy", findQuietAgents, (self.app.api,), {})
|
||||
case "otp_activities_button":
|
||||
_PENDING_JOB = ("legacy", otp_activities_by_agent, (self.app.api,), {})
|
||||
case "otp_revoke_button":
|
||||
@@ -353,7 +356,6 @@ class Loxide(App):
|
||||
text-align: center;
|
||||
}
|
||||
"""
|
||||
|
||||
BINDINGS = [
|
||||
("q", "quit", "Quit"),
|
||||
("d", "open_dir", "Open Directory"),
|
||||
@@ -367,17 +369,20 @@ class Loxide(App):
|
||||
if not os.path.isdir(wd):
|
||||
wd = os.getcwd()
|
||||
self.working_dir = wd
|
||||
# Initial data load
|
||||
self.refresh_data()
|
||||
|
||||
# Add error handling for API calls
|
||||
def refresh_data(self) -> None:
|
||||
"""Public method to refresh policies and devices from the API."""
|
||||
try:
|
||||
self.policies = [
|
||||
Policy(**row.to_dict()) for _, row in api.policy_find_all().iterrows()
|
||||
Policy(**row.to_dict())
|
||||
for _, row in self.api.policy_find_all().iterrows()
|
||||
]
|
||||
self.devices = [
|
||||
Agent(**row.to_dict()) for _, row in api.agent_find_all().iterrows()
|
||||
Agent(**row.to_dict())
|
||||
for _, row in self.api.agent_find_all().iterrows()
|
||||
]
|
||||
|
||||
# Enrich agents with policy information
|
||||
if self.policies and self.devices:
|
||||
for agent in self.devices:
|
||||
agent.enrich_with_policies(self.policies)
|
||||
@@ -401,6 +406,8 @@ class Loxide(App):
|
||||
self.exit()
|
||||
|
||||
def action_open_dir(self) -> None:
|
||||
# Refresh data before proceeding
|
||||
self.refresh_data()
|
||||
screen = self.screen_stack[-1]
|
||||
if isinstance(screen, MainMenuScreen):
|
||||
if screen.current_tab != "dir":
|
||||
@@ -417,7 +424,6 @@ def _restore_terminal_for_legacy() -> None:
|
||||
sys.stdout.write("\033[?1000l\033[?1002l\033[?1003l\033[?1006l")
|
||||
sys.stdout.write("\033[2J\033[H")
|
||||
sys.stdout.flush()
|
||||
|
||||
if os.name == "nt":
|
||||
try:
|
||||
import ctypes
|
||||
@@ -434,7 +440,6 @@ def _restore_terminal_for_legacy() -> None:
|
||||
def _run_legacy_job(func, args, kwargs) -> None:
|
||||
logger.debug("Running legacy job: %s", getattr(func, "__name__", func))
|
||||
_restore_terminal_for_legacy()
|
||||
|
||||
try:
|
||||
func(*args, **kwargs)
|
||||
finally:
|
||||
@@ -449,24 +454,31 @@ def _run_legacy_job(func, args, kwargs) -> None:
|
||||
# ---------------------------------------------------------------------------
|
||||
def run_Loxide(api: AirlockAPIWrapper) -> None:
|
||||
global _PENDING_JOB
|
||||
|
||||
while True:
|
||||
base_dir = get_base_directory()
|
||||
env_path = base_dir / ".env"
|
||||
dotenv.load_dotenv(dotenv_path=env_path, override=True)
|
||||
|
||||
max_attempts = 5
|
||||
attempts = 0
|
||||
|
||||
while attempts < max_attempts:
|
||||
attempts += 1
|
||||
logger.debug("Starting job loop iteration (attempt %d)", attempts)
|
||||
_PENDING_JOB = None
|
||||
app = Loxide(api)
|
||||
|
||||
try:
|
||||
app.run()
|
||||
except SystemExit as exc:
|
||||
if exc.code != 0:
|
||||
logger.debug("Caught SystemExit from Textual: %s", exc)
|
||||
raise
|
||||
|
||||
job = _PENDING_JOB
|
||||
logger.debug("After app.run(), _PENDING_JOB = %r", job)
|
||||
|
||||
if not job:
|
||||
logger.debug("No job pending, exiting loop")
|
||||
break
|
||||
|
||||
if job[0] == "legacy":
|
||||
@@ -475,49 +487,24 @@ def run_Loxide(api: AirlockAPIWrapper) -> None:
|
||||
continue
|
||||
|
||||
if job[0] == "restart":
|
||||
# just loop again; fresh .env was already loaded at the top
|
||||
logger.debug("Restarting job loop")
|
||||
continue
|
||||
|
||||
if job[0] == "multi_agent_action":
|
||||
# Handle multi-agent selection
|
||||
logger.info("Multi-agent action with selected agents: %s", job[1])
|
||||
continue
|
||||
|
||||
# NEW: Handle OTP workflow
|
||||
if job[0] == "otp_workflow":
|
||||
_, devices, requestor, reasoning, duration = job
|
||||
|
||||
# Call your OTP generation with the parameters
|
||||
def otp_generate_with_params():
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print("OTP GENERATION")
|
||||
print(f"{'='*60}")
|
||||
print(f"Requestor: {requestor}")
|
||||
print(f"Reasoning: {reasoning}")
|
||||
print(f"Duration: {duration} minutes")
|
||||
print(f"\nGenerating OTPs for {len(devices)} devices:")
|
||||
print(f"{'='*60}\n")
|
||||
|
||||
# Call your actual OTP generation function
|
||||
# You'll need to adapt otp_generate to accept these parameters
|
||||
# For now, this is a placeholder showing the structure
|
||||
for device in devices:
|
||||
print(f"Device: {device}")
|
||||
print(f" Requestor: {requestor}")
|
||||
print(f" Reason: {reasoning}")
|
||||
print(f" Duration: {duration} minutes")
|
||||
# TODO: Actually call your API to generate OTP
|
||||
# result = api.generate_otp(device, requestor, reasoning, duration)
|
||||
print()
|
||||
|
||||
print(f"{'='*60}")
|
||||
print("OTP Generation Complete!")
|
||||
print(f"{'='*60}")
|
||||
# Your OTP logic here
|
||||
pass
|
||||
|
||||
_run_legacy_job(otp_generate_with_params, (), {})
|
||||
continue
|
||||
|
||||
logger.error("Unknown job type: %r", job)
|
||||
break
|
||||
|
||||
|
||||
|
||||
@@ -506,6 +506,7 @@ class AgentMoveOperations(Widget):
|
||||
unsuccessful = []
|
||||
status_label = self.query_one("#status_label", Static)
|
||||
status_label.update("Exporting CSV...")
|
||||
self.app.refresh_data()
|
||||
agents = self.agents
|
||||
policies = self.app.policies
|
||||
path = self.app.working_dir
|
||||
@@ -604,6 +605,8 @@ class AgentMoveOperations(Widget):
|
||||
|
||||
successful.append((agent, f"Moved to {mode}: {result}"))
|
||||
logger.info(f"Successfully toggled {agent.hostname} to {mode}")
|
||||
self.app.refresh_data()
|
||||
|
||||
except Exception as e:
|
||||
unsuccessful.append((agent, str(e)))
|
||||
logger.error(f"Failed to toggle {agent.hostname}: {e}")
|
||||
@@ -728,7 +731,7 @@ class AgentMoveOperations(Widget):
|
||||
status_label.update(f"Error: {str(e)}")
|
||||
self.operation_in_progress = False
|
||||
return
|
||||
|
||||
self.app.refresh_data()
|
||||
self.operation_in_progress = False
|
||||
status_label.update("Operation complete!")
|
||||
|
||||
|
||||
@@ -80,11 +80,11 @@ class MultiAgentSelector(Widget):
|
||||
select_buttons.styles.margin = (0, 0, 0, 0)
|
||||
|
||||
select_none_button = Button("🚫 Select None", id="select_none")
|
||||
select_none_button.styles.margin = (1, 0, 0, 1)
|
||||
select_none_button.styles.margin = (1, 1, 0, 1)
|
||||
yield select_none_button
|
||||
|
||||
select_all_button = Button("✅ Select All", id="select_all")
|
||||
select_all_button.styles.margin = (1, 1, 0, 1)
|
||||
select_all_button.styles.margin = (1, 0, 0, 1)
|
||||
yield select_all_button
|
||||
|
||||
with Horizontal() as button_row:
|
||||
@@ -93,6 +93,7 @@ class MultiAgentSelector(Widget):
|
||||
|
||||
back_button = Button("← Back", id="back_button")
|
||||
back_button.styles.width = "1fr"
|
||||
back_button.styles.margin = (0, 0, 0, 1)
|
||||
yield back_button
|
||||
|
||||
submit_button = Button(
|
||||
|
||||
Reference in New Issue
Block a user