Skip to content

Commit

Permalink
handle the start recovery and cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
mojtaba-esk committed Jan 24, 2025
1 parent 3c0bd3b commit 6c74393
Show file tree
Hide file tree
Showing 8 changed files with 286 additions and 57 deletions.
25 changes: 20 additions & 5 deletions cmd/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"

"github.com/celestiaorg/knuu/internal/api/v1"
"github.com/celestiaorg/knuu/internal/api/v1/services"
"github.com/celestiaorg/knuu/internal/database"

"github.com/gin-gonic/gin"
Expand All @@ -28,18 +29,22 @@ const (
flagAdminUser = "admin-user"
flagAdminPass = "admin-pass"

flagLogsPath = "logs-path"

defaultPort = 8080
defaultLogLevel = gin.ReleaseMode

defaultDBHost = "localhost"
defaultDBUser = "postgres"
defaultDBPassword = "postgres"
defaultDBName = "postgres"
defaultDBPort = 5432
defaultDBHost = database.DefaultHost
defaultDBUser = database.DefaultUser
defaultDBPassword = database.DefaultPassword
defaultDBName = database.DefaultDBName
defaultDBPort = database.DefaultPort

defaultSecretKey = "secret"
defaultAdminUser = "admin"
defaultAdminPass = "admin"

defaultLogsPath = services.DefaultLogsPath
)

func NewAPICmd() *cobra.Command {
Expand All @@ -63,6 +68,8 @@ func NewAPICmd() *cobra.Command {
apiCmd.Flags().StringP(flagAdminUser, "", defaultAdminUser, "Admin username")
apiCmd.Flags().StringP(flagAdminPass, "", defaultAdminPass, "Admin password")

apiCmd.Flags().StringP(flagLogsPath, "", defaultLogsPath, "Path to store logs")

return apiCmd
}

Expand Down Expand Up @@ -151,11 +158,19 @@ func getAPIOptions(flags *pflag.FlagSet) (api.Options, error) {
return api.Options{}, fmt.Errorf("failed to get admin password: %v", err)
}

logsPath, err := flags.GetString(flagLogsPath)
if err != nil {
return api.Options{}, fmt.Errorf("failed to get logs path: %v", err)
}

return api.Options{
Port: port,
LogMode: logLevel,
SecretKey: secretKey,
AdminUser: adminUser,
AdminPass: adminPass,
TestServiceOptions: services.TestServiceOptions{
LogsPath: logsPath,
},
}, nil
}
43 changes: 26 additions & 17 deletions internal/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@ const (
defaultLogMode = gin.ReleaseMode
)

type apiCleanup struct {
testService *services.TestService
}

type API struct {
router *gin.Engine
server *http.Server
router *gin.Engine
server *http.Server
cleanup apiCleanup
}

type Options struct {
Expand All @@ -34,6 +39,8 @@ type Options struct {

AdminUser string // default admin username
AdminPass string // default admin password

TestServiceOptions services.TestServiceOptions
}

func New(ctx context.Context, db *gorm.DB, opts Options) (*API, error) {
Expand All @@ -53,19 +60,21 @@ func New(ctx context.Context, db *gorm.DB, opts Options) (*API, error) {
public.POST(pathsUserLogin, uh.Login)
}

testService, err := services.NewTestService(ctx, repos.NewTestRepository(db), opts.TestServiceOptions)
if err != nil {
return nil, err
}

protected := rt.Group("/", auth.AuthMiddleware())
{
protected.POST(pathsUserRegister, auth.RequireRole(models.RoleAdmin), uh.Register)

th, err := getTestHandler(ctx, db)
if err != nil {
return nil, err
}

th := handlers.NewTestHandler(testService)
protected.POST(pathsTests, th.CreateTest)
// protected.GET(pathsTestDetails, th.GetTestDetails)
// protected.GET(pathsTestInstances, th.GetInstances)
protected.GET(pathsTestInstanceDetails, th.GetInstance)
protected.GET(pathsTestInstanceStatus, th.GetInstanceStatus)
protected.POST(pathsTestInstanceDetails, th.CreateInstance) // Need to do something about updating an instance
// protected.POST(pathsTestInstanceExecute, th.ExecuteInstance)
}
Expand All @@ -78,6 +87,9 @@ func New(ctx context.Context, db *gorm.DB, opts Options) (*API, error) {
Addr: fmt.Sprintf(":%d", opts.Port),
Handler: handleOrigin(rt, opts.OriginAllowed),
},
cleanup: apiCleanup{
testService: testService,
},
}

if opts.LogMode != gin.ReleaseMode {
Expand All @@ -92,8 +104,14 @@ func (a *API) Start() error {
return a.server.ListenAndServe()
}

func (a *API) Stop() error {
func (a *API) Stop(ctx context.Context) error {
fmt.Println("Shutting down API server")
if a.cleanup.testService != nil {
err := a.cleanup.testService.Shutdown(ctx)
if err != nil {
return err
}
}
return a.server.Close()
}

Expand Down Expand Up @@ -137,12 +155,3 @@ func getUserHandler(ctx context.Context, opts Options, db *gorm.DB, auth *middle

return handlers.NewUserHandler(us, auth), nil
}

func getTestHandler(ctx context.Context, db *gorm.DB) (*handlers.TestHandler, error) {
ts, err := services.NewTestService(ctx, repos.NewTestRepository(db))
if err != nil {
return nil, err
}

return handlers.NewTestHandler(ts), nil
}
17 changes: 16 additions & 1 deletion internal/api/v1/handlers/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,25 @@ func (h *TestHandler) GetInstance(c *gin.Context) {
return
}

instance, err := h.testService.GetInstance(c.Request.Context(), user.ID, c.Param("scope"), c.Param("instance_name"))
instance, err := h.testService.GetInstance(c.Request.Context(), user.ID, c.Param("scope"), c.Param("name"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, instance)
}

func (h *TestHandler) GetInstanceStatus(c *gin.Context) {
user, err := getUserFromContext(c)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
return
}

status, err := h.testService.GetInstanceStatus(c.Request.Context(), user.ID, c.Param("scope"), c.Param("name"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"status": status})
}
5 changes: 4 additions & 1 deletion internal/api/v1/paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const (
pathsTests = pathsPrefix + "/tests"
pathsTestDetails = pathsTests + "/{scope}"
pathsTestInstances = pathsTestDetails + "/instances"
pathsTestInstanceDetails = pathsTestInstances + "/{instance_id}"
pathsTestInstanceDetails = pathsTestInstances + "/{name}"
pathsTestInstanceStatus = pathsTestInstanceDetails + "/status"
pathsTestInstanceLogs = pathsTestInstanceDetails + "/logs"
pathsTestInstanceStop = pathsTestInstanceDetails + "/stop"
pathsTestInstanceExecute = pathsTestInstanceDetails + "/execute"
)
25 changes: 21 additions & 4 deletions internal/api/v1/services/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ type Instance struct {
BuildArgs []string `json:"build_args"`
StartCommand []string `json:"start_command"`
Args []string `json:"args"`
Status string `json:"status"` // Readonly
StartNow bool `json:"start_now"`
Env map[string]string `json:"env"`
TCPPorts []int `json:"tcp_ports"`
Expand Down Expand Up @@ -87,10 +86,14 @@ func (s *TestService) CreateInstance(ctx context.Context, userID uint, instance
}
}

if instance.StartNow {
return ins.Execution().StartAsync(ctx)
if !instance.StartNow {
return nil
}
return nil

if err := ins.Build().Commit(ctx); err != nil {
return err
}
return ins.Execution().StartAsync(ctx)
}

func (s *TestService) GetInstance(ctx context.Context, userID uint, scope, instanceName string) (*Instance, error) {
Expand All @@ -103,3 +106,17 @@ func (s *TestService) GetInstance(ctx context.Context, userID uint, scope, insta

return nil, fmt.Errorf("not implemented")
}

func (s *TestService) GetInstanceStatus(ctx context.Context, userID uint, scope, instanceName string) (string, error) {
kn, err := s.Knuu(userID, scope)
if err != nil {
return "", err
}

ps, err := kn.K8sClient.PodStatus(ctx, instanceName)
if err != nil {
return "", err
}

return string(ps.Status), nil
}
Loading

0 comments on commit 6c74393

Please sign in to comment.