startNativeAgentWithPTY starts the agent with PTY support for interactive input (e.g., sudo password)
(ctx context.Context, keployBin string, args []string, grp *errgroup.Group)
| 1028 | |
| 1029 | // startNativeAgentWithPTY starts the agent with PTY support for interactive input (e.g., sudo password) |
| 1030 | func (a *AgentClient) startNativeAgentWithPTY(ctx context.Context, keployBin string, args []string, grp *errgroup.Group) error { |
| 1031 | // Create command configured for PTY |
| 1032 | cmd := agentUtils.NewAgentCommandForPTY(keployBin, args) |
| 1033 | |
| 1034 | a.logger.Debug("Starting native agent with PTY for interactive input") |
| 1035 | |
| 1036 | // Start with PTY |
| 1037 | ptyHandle, err := agentUtils.StartCommandWithPTY(cmd, a.logger) |
| 1038 | if err != nil { |
| 1039 | utils.LogError(a.logger, err, "failed to start keploy agent with PTY") |
| 1040 | return err |
| 1041 | } |
| 1042 | |
| 1043 | a.mu.Lock() |
| 1044 | a.agentCmd = cmd |
| 1045 | a.agentPTY = ptyHandle |
| 1046 | a.mu.Unlock() |
| 1047 | |
| 1048 | pid := cmd.Process.Pid |
| 1049 | a.logger.Debug("keploy agent started with PTY", zap.Int("pid", pid)) |
| 1050 | |
| 1051 | grp.Go(func() error { |
| 1052 | defer utils.Recover(a.logger) |
| 1053 | |
| 1054 | err := ptyHandle.Wait() |
| 1055 | // If ctx wasn't cancelled, bubble up unexpected exits |
| 1056 | if err != nil && ctx.Err() == nil { |
| 1057 | a.logger.Error("agent process exited with error", zap.Error(err)) |
| 1058 | return err |
| 1059 | } |
| 1060 | a.mu.Lock() |
| 1061 | a.agentCmd = nil |
| 1062 | a.agentPTY = nil |
| 1063 | a.mu.Unlock() |
| 1064 | a.logger.Debug("agent process stopped") |
| 1065 | return nil |
| 1066 | }) |
| 1067 | |
| 1068 | grp.Go(func() error { |
| 1069 | defer utils.Recover(a.logger) |
| 1070 | <-ctx.Done() |
| 1071 | if a.conf.Agent.AgentURI == "" { |
| 1072 | return nil |
| 1073 | } |
| 1074 | a.logger.Debug("Keploy agent shutdown requested", zap.Int("pid", pid)) |
| 1075 | a.logger.Info("Stopping keploy agent") |
| 1076 | if err := a.requestAgentStop(); err != nil { |
| 1077 | a.logger.Debug("failed to request keploy agent shutdown, sending stop signal", zap.Error(err)) |
| 1078 | // Fallback: forcefully stop the agent process |
| 1079 | a.mu.Lock() |
| 1080 | ptyHandle := a.agentPTY |
| 1081 | a.mu.Unlock() |
| 1082 | if ptyHandle != nil { |
| 1083 | if stopErr := agentUtils.StopPTYCommand(ptyHandle, a.logger); stopErr != nil { |
| 1084 | a.logger.Error("failed to forcefully stop agent", zap.Error(stopErr)) |
| 1085 | } |
| 1086 | } |
| 1087 | return nil |
no test coverage detected