diff --git a/cli/cdsctl/admin.go b/cli/cdsctl/admin.go index 3686006d9f..d78dacc68e 100644 --- a/cli/cdsctl/admin.go +++ b/cli/cdsctl/admin.go @@ -16,6 +16,7 @@ func adminCommands() []*cobra.Command { adminDatabase(), adminServices(), adminCdn(), + adminRepositories(), adminHooks(), adminOrganization(), adminIntegrationModels(), diff --git a/cli/cdsctl/admin_repositories.go b/cli/cdsctl/admin_repositories.go new file mode 100644 index 0000000000..32d30d9523 --- /dev/null +++ b/cli/cdsctl/admin_repositories.go @@ -0,0 +1,37 @@ +package main + +import ( + "github.com/spf13/cobra" + + "github.com/ovh/cds/cli" + "github.com/ovh/cds/sdk" +) + +var adminRepositoriesCmd = cli.Command{ + Name: "repositories", + Short: "Manage CDS repositories uService", +} + +func adminRepositories() *cobra.Command { + return cli.NewCommand(adminRepositoriesCmd, nil, []*cobra.Command{ + cli.NewListCommand(adminRepositorisStatusCmd, adminRepositorisStatusRun, nil), + }) +} + +func adminRepositorisStatusRun(_ cli.Values) (cli.ListResult, error) { + services, err := client.ServicesByType(sdk.TypeRepositories) + if err != nil { + return nil, err + } + status := sdk.MonitoringStatus{} + for _, srv := range services { + status.Lines = append(status.Lines, srv.MonitoringStatus.Lines...) + } + return cli.AsListResult(status.Lines), nil +} + +var adminRepositorisStatusCmd = cli.Command{ + Name: "status", + Short: "display the status of repositories", + Example: "cdsctl admin repositories status", +} diff --git a/engine/repositories/fs.go b/engine/repositories/fs.go index 38e1528604..d3c1a77179 100644 --- a/engine/repositories/fs.go +++ b/engine/repositories/fs.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path/filepath" + "time" "github.com/rockbears/log" @@ -42,3 +43,31 @@ func (s *Service) cleanFS(ctx context.Context, r *sdk.OperationRepo) error { log.Info(ctx, "cleaning operation basedir: %v", r.Basedir) return sdk.WithStack(os.RemoveAll(r.Basedir)) } + +func (s *Service) computeCacheSize(ctx context.Context) error { + tick := time.NewTicker(5 * time.Minute) + + defer tick.Stop() + for { + select { + case <-tick.C: + var size int64 + err := filepath.Walk(s.Cfg.Basedir, func(_ string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() { + size += info.Size() + } + return err + }) + if err != nil { + log.ErrorWithStackTrace(ctx, sdk.WrapError(err, "unable to compute size")) + continue + } + s.cacheSize = size + case <-ctx.Done(): + return ctx.Err() + } + } +} diff --git a/engine/repositories/repositories.go b/engine/repositories/repositories.go index a5b03d2064..867559abbd 100644 --- a/engine/repositories/repositories.go +++ b/engine/repositories/repositories.go @@ -106,18 +106,25 @@ func (s *Service) Serve(c context.Context) error { } log.Info(ctx, "Initializing processor...") - go func() { + s.GoRoutines.RunWithRestart(ctx, "processor", func(ctx context.Context) { if err := s.processor(ctx); err != nil { - log.Info(ctx, "Shutdown processor") + log.ErrorWithStackTrace(ctx, err) } - }() + }) log.Info(ctx, "Initializing vacuumCleaner...") - go func() { + s.GoRoutines.RunWithRestart(ctx, "vacuumCleaner", func(ctx context.Context) { if err := s.vacuumCleaner(ctx); err != nil { - log.Info(ctx, "Shutdown vacuumCleaner") + log.ErrorWithStackTrace(ctx, err) } - }() + }) + + log.Info(ctx, "Initializing cache size...") + s.GoRoutines.RunWithRestart(ctx, "computeCacheSize", func(ctx context.Context) { + if err := s.computeCacheSize(ctx); err != nil { + log.ErrorWithStackTrace(ctx, err) + } + }) //Gracefully shutdown the http server go func() { diff --git a/engine/repositories/repositories_handlers.go b/engine/repositories/repositories_handlers.go index 7e1cfd982f..f8f013cd5f 100644 --- a/engine/repositories/repositories_handlers.go +++ b/engine/repositories/repositories_handlers.go @@ -4,6 +4,7 @@ import ( "archive/tar" "bytes" "context" + "fmt" "io" "net/http" "strings" @@ -133,6 +134,12 @@ func (s *Service) getOperationsHandler() service.Handler { // Status returns sdk.MonitoringStatus, implements interface service.Service func (s *Service) Status(ctx context.Context) *sdk.MonitoringStatus { m := s.NewMonitoringStatus() + + m.Lines = append(m.Lines, sdk.MonitoringStatusLine{ + Component: "Cache size", + Value: fmt.Sprintf("%d octets", s.cacheSize), + Status: sdk.MonitoringStatusOK, + }) return m } diff --git a/engine/repositories/types.go b/engine/repositories/types.go index eaf440d254..93310ad49d 100644 --- a/engine/repositories/types.go +++ b/engine/repositories/types.go @@ -13,10 +13,11 @@ import ( // Service is the repostories service type Service struct { service.Common - Cfg Configuration - Router *api.Router - Cache cache.Store - dao dao + Cfg Configuration + Router *api.Router + Cache cache.Store + dao dao + cacheSize int64 } // Configuration is the vcs configuration structure