diff --git a/src/shidai/internal/commands/commands.go b/src/shidai/internal/commands/commands.go index a20a752..abba1c5 100644 --- a/src/shidai/internal/commands/commands.go +++ b/src/shidai/internal/commands/commands.go @@ -6,7 +6,9 @@ import ( "net/http" "os" "strconv" + "time" + dtypes "github.com/docker/docker/api/types" "github.com/kiracore/sekin/src/shidai/internal/docker" interxhandler "github.com/kiracore/sekin/src/shidai/internal/interx_handler" interxhelper "github.com/kiracore/sekin/src/shidai/internal/interx_handler/interx_helper" @@ -46,6 +48,7 @@ var ( "start": handleStartComamnd, "tx": handleTxCommand, "sekaid": handleSekaidCommand, + "stop": handleStopCommand, } ) @@ -272,3 +275,71 @@ func handleStartComamnd(args map[string]interface{}) (string, error) { } return "Sekai and Interx started successfully", nil } + +func handleStopCommand(args map[string]interface{}) (string, error) { + cm, err := docker.NewContainerManager() + if err != nil { + return "", err + } + ctx := context.Background() + + running, err := cm.ContainerIsRunning(ctx, types.SEKAI_CONTAINER_ID) + if err != nil { + return "", err + } + if running { + sekaiErr := cm.KillContainerWithSigkill(ctx, types.SEKAI_CONTAINER_ID, types.SIGTERM) + if sekaiErr != nil { + return "", err + } + for i := range 5 { + log.Debug("checking if container is stopped") + stopped, sekaiErr := cm.ContainerIsStopped(ctx, types.SEKAI_CONTAINER_ID) + if sekaiErr != nil { + return "", err + } + if stopped { + sekaiErr = cm.Cli.ContainerStart(ctx, types.SEKAI_CONTAINER_ID, dtypes.ContainerStartOptions{}) + if sekaiErr != nil { + return "", err + } + break + } else { + log.Debug("container is not stopped yet, waiting to shutdown", zap.Int("attempt", i)) + time.Sleep(time.Second) + } + + } + } + + running, err = cm.ContainerIsRunning(ctx, types.INTERX_CONTAINER_ID) + if err != nil { + return "", err + } + if running { + interxErr := cm.KillContainerWithSigkill(ctx, types.INTERX_CONTAINER_ID, types.SIGKILL) + if interxErr != nil { + return "", err + } + + for i := range 5 { + log.Debug("checking if container is stopped") + stopped, interxErr := cm.ContainerIsStopped(ctx, types.INTERX_CONTAINER_ID) + if interxErr != nil { + return "", err + } + if stopped { + interxErr = cm.Cli.ContainerStart(ctx, types.INTERX_CONTAINER_ID, dtypes.ContainerStartOptions{}) + if interxErr != nil { + return "", err + } + break + } else { + log.Debug("container is not stopped yet, waiting to shutdown", zap.Int("attempt", i)) + time.Sleep(time.Second) + } + } + } + + return "Sekai and Interx stoped seccessfully", nil +} diff --git a/src/shidai/internal/docker/docker.go b/src/shidai/internal/docker/docker.go index a5b2212..b605469 100644 --- a/src/shidai/internal/docker/docker.go +++ b/src/shidai/internal/docker/docker.go @@ -69,3 +69,39 @@ func (cm *ContainerManager) ExecInContainer(ctx context.Context, containerID str log.Info("Command executed successfully", zap.String("output", string(output))) return output, nil } + +func (cm *ContainerManager) KillContainerWithSigkill(ctx context.Context, containerID, signal string) error { + log.Debug("Killing container", zap.String("container id", containerID), zap.String("kill signal", signal)) + + err := cm.Cli.ContainerKill(ctx, containerID, signal) + if err != nil { + return err + } + return nil +} + +func (cm *ContainerManager) ContainerIsRunning(ctx context.Context, containerName string) (bool, error) { + containers, err := cm.Cli.ContainerList(context.Background(), types.ContainerListOptions{}) + if err != nil { + return false, err + } + for _, container := range containers { + for _, name := range container.Names { + if name == "/"+containerName && container.State == "running" { + return true, nil + } + } + } + + return false, nil +} + +func (cm *ContainerManager) ContainerIsStopped(ctx context.Context, containerID string) (bool, error) { + containerJSON, err := cm.Cli.ContainerInspect(ctx, containerID) + if err != nil { + return false, err // Handle the error, it might be that the container does not exist + } + log.Debug("checking if container is stopped", zap.String("container name", containerID), zap.String("container status", containerJSON.State.Status)) + // The State.Status will tell if the container is "exited", "running", etc. + return containerJSON.State.Status == "exited", nil +} diff --git a/src/shidai/internal/types/types.go b/src/shidai/internal/types/types.go index 39d6c1a..7706701 100644 --- a/src/shidai/internal/types/types.go +++ b/src/shidai/internal/types/types.go @@ -286,7 +286,11 @@ const ( DirPermRO os.FileMode = 0555 DirPermWR os.FileMode = 0755 - UPDATER_BIN_PATH = "/updater" + UPDATER_BIN_PATH = "/updater" + SEKIN_LATEST_COMPOSE_URL = "https://raw.githubusercontent.com/KiraCore/sekin/main/compose.yml" + + SIGKILL string = "SIGKILL" // 9 - interx + SIGTERM string = "SIGTERM" // 15 - sekai ) var (