2014-03-20 15:50:26 +04:00
// Copyright 2014 The Gogs Authors. All rights reserved.
2019-06-26 19:12:38 +03:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2014-03-20 15:50:26 +04:00
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package admin
import (
2019-11-14 23:06:02 +03:00
"encoding/json"
2014-03-22 15:42:24 +04:00
"fmt"
2019-06-26 19:12:38 +03:00
"net/url"
2019-03-20 01:40:13 +03:00
"os"
2014-03-22 15:42:24 +04:00
"runtime"
2020-01-07 14:23:09 +03:00
"strconv"
2014-03-21 11:27:59 +04:00
"strings"
2014-03-22 15:42:24 +04:00
"time"
2014-03-21 11:27:59 +04:00
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/cron"
2019-05-15 04:57:00 +03:00
"code.gitea.io/gitea/modules/git"
2019-12-15 12:51:28 +03:00
"code.gitea.io/gitea/modules/graceful"
2019-06-26 19:12:38 +03:00
"code.gitea.io/gitea/modules/log"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/process"
2020-01-07 14:23:09 +03:00
"code.gitea.io/gitea/modules/queue"
2020-01-20 23:01:19 +03:00
repo_module "code.gitea.io/gitea/modules/repository"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/setting"
2019-08-15 17:46:21 +03:00
"code.gitea.io/gitea/modules/timeutil"
2019-09-24 08:02:49 +03:00
"code.gitea.io/gitea/services/mailer"
2019-08-23 19:40:30 +03:00
"gitea.com/macaron/macaron"
2019-11-14 23:06:02 +03:00
"gitea.com/macaron/session"
2019-08-23 19:40:30 +03:00
"github.com/unknwon/com"
2014-03-20 15:50:26 +04:00
)
2014-06-22 21:14:03 +04:00
const (
2016-11-21 06:21:24 +03:00
tplDashboard base . TplName = "admin/dashboard"
tplConfig base . TplName = "admin/config"
tplMonitor base . TplName = "admin/monitor"
2020-01-07 14:23:09 +03:00
tplQueue base . TplName = "admin/queue"
2014-06-22 21:14:03 +04:00
)
2014-07-07 12:15:08 +04:00
var (
startTime = time . Now ( )
)
2014-03-22 17:21:57 +04:00
2014-03-22 15:42:24 +04:00
var sysStatus struct {
2014-03-22 17:21:57 +04:00
Uptime string
2014-03-22 15:42:24 +04:00
NumGoroutine int
// General statistics.
MemAllocated string // bytes allocated and still in use
MemTotal string // bytes allocated (even if freed)
MemSys string // bytes obtained from system (sum of XxxSys below)
Lookups uint64 // number of pointer lookups
MemMallocs uint64 // number of mallocs
MemFrees uint64 // number of frees
// Main allocation heap statistics.
HeapAlloc string // bytes allocated and still in use
HeapSys string // bytes obtained from system
HeapIdle string // bytes in idle spans
HeapInuse string // bytes in non-idle span
HeapReleased string // bytes released to the OS
HeapObjects uint64 // total number of allocated objects
// Low-level fixed-size structure allocator statistics.
// Inuse is bytes used now.
// Sys is bytes obtained from system.
StackInuse string // bootstrap stacks
StackSys string
MSpanInuse string // mspan structures
MSpanSys string
MCacheInuse string // mcache structures
MCacheSys string
BuckHashSys string // profiling bucket hash table
GCSys string // GC metadata
OtherSys string // other system allocations
// Garbage collector statistics.
NextGC string // next run in HeapAlloc time (bytes)
LastGC string // last run in absolute time (ns)
PauseTotalNs string
PauseNs string // circular buffer of recent GC pause times, most recent at [(NumGC+255)%256]
NumGC uint32
}
func updateSystemStatus ( ) {
2019-08-15 17:46:21 +03:00
sysStatus . Uptime = timeutil . TimeSincePro ( startTime , "en" )
2014-03-22 17:21:57 +04:00
2014-03-22 15:42:24 +04:00
m := new ( runtime . MemStats )
runtime . ReadMemStats ( m )
sysStatus . NumGoroutine = runtime . NumGoroutine ( )
sysStatus . MemAllocated = base . FileSize ( int64 ( m . Alloc ) )
sysStatus . MemTotal = base . FileSize ( int64 ( m . TotalAlloc ) )
sysStatus . MemSys = base . FileSize ( int64 ( m . Sys ) )
sysStatus . Lookups = m . Lookups
sysStatus . MemMallocs = m . Mallocs
sysStatus . MemFrees = m . Frees
sysStatus . HeapAlloc = base . FileSize ( int64 ( m . HeapAlloc ) )
sysStatus . HeapSys = base . FileSize ( int64 ( m . HeapSys ) )
sysStatus . HeapIdle = base . FileSize ( int64 ( m . HeapIdle ) )
sysStatus . HeapInuse = base . FileSize ( int64 ( m . HeapInuse ) )
sysStatus . HeapReleased = base . FileSize ( int64 ( m . HeapReleased ) )
sysStatus . HeapObjects = m . HeapObjects
sysStatus . StackInuse = base . FileSize ( int64 ( m . StackInuse ) )
sysStatus . StackSys = base . FileSize ( int64 ( m . StackSys ) )
sysStatus . MSpanInuse = base . FileSize ( int64 ( m . MSpanInuse ) )
sysStatus . MSpanSys = base . FileSize ( int64 ( m . MSpanSys ) )
sysStatus . MCacheInuse = base . FileSize ( int64 ( m . MCacheInuse ) )
sysStatus . MCacheSys = base . FileSize ( int64 ( m . MCacheSys ) )
sysStatus . BuckHashSys = base . FileSize ( int64 ( m . BuckHashSys ) )
sysStatus . GCSys = base . FileSize ( int64 ( m . GCSys ) )
sysStatus . OtherSys = base . FileSize ( int64 ( m . OtherSys ) )
sysStatus . NextGC = base . FileSize ( int64 ( m . NextGC ) )
sysStatus . LastGC = fmt . Sprintf ( "%.1fs" , float64 ( time . Now ( ) . UnixNano ( ) - int64 ( m . LastGC ) ) / 1000 / 1000 / 1000 )
2014-03-22 17:21:57 +04:00
sysStatus . PauseTotalNs = fmt . Sprintf ( "%.1fs" , float64 ( m . PauseTotalNs ) / 1000 / 1000 / 1000 )
sysStatus . PauseNs = fmt . Sprintf ( "%.3fs" , float64 ( m . PauseNs [ ( m . NumGC + 255 ) % 256 ] ) / 1000 / 1000 / 1000 )
2014-03-22 15:42:24 +04:00
sysStatus . NumGC = m . NumGC
}
2016-11-21 06:21:24 +03:00
// Operation Operation types.
type Operation int
2014-06-21 08:51:41 +04:00
2014-05-06 21:47:47 +04:00
const (
2016-11-21 06:21:24 +03:00
cleanInactivateUser Operation = iota + 1
cleanRepoArchives
cleanMissingRepos
gitGCRepos
syncSSHAuthorizedKey
syncRepositoryUpdateHook
reinitMissingRepository
2017-05-10 16:10:18 +03:00
syncExternalUsers
2018-03-02 12:09:43 +03:00
gitFsck
2019-06-02 09:40:12 +03:00
deleteGeneratedRepositoryAvatars
2014-05-06 21:47:47 +04:00
)
2016-11-21 06:21:24 +03:00
// Dashboard show admin panel dashboard
2016-03-11 19:56:52 +03:00
func Dashboard ( ctx * context . Context ) {
2014-08-28 18:29:00 +04:00
ctx . Data [ "Title" ] = ctx . Tr ( "admin.dashboard" )
ctx . Data [ "PageIsAdmin" ] = true
ctx . Data [ "PageIsAdminDashboard" ] = true
2014-05-06 21:47:47 +04:00
// Run operation.
2014-07-26 08:24:27 +04:00
op , _ := com . StrTo ( ctx . Query ( "op" ) ) . Int ( )
2014-05-06 21:47:47 +04:00
if op > 0 {
var err error
var success string
2020-01-20 23:01:19 +03:00
shutdownCtx := graceful . GetManager ( ) . ShutdownContext ( )
2014-05-06 21:47:47 +04:00
2016-11-21 06:21:24 +03:00
switch Operation ( op ) {
case cleanInactivateUser :
2014-11-19 03:05:33 +03:00
success = ctx . Tr ( "admin.dashboard.delete_inactivate_accounts_success" )
2014-06-21 08:51:41 +04:00
err = models . DeleteInactivateUsers ( )
2016-11-21 06:21:24 +03:00
case cleanRepoArchives :
2014-11-19 03:05:33 +03:00
success = ctx . Tr ( "admin.dashboard.delete_repo_archives_success" )
err = models . DeleteRepositoryArchives ( )
2016-11-21 06:21:24 +03:00
case cleanMissingRepos :
2015-11-18 23:37:48 +03:00
success = ctx . Tr ( "admin.dashboard.delete_missing_repos_success" )
2020-01-20 23:01:19 +03:00
err = repo_module . DeleteMissingRepositories ( ctx . User )
2016-11-21 06:21:24 +03:00
case gitGCRepos :
2014-11-30 10:26:29 +03:00
success = ctx . Tr ( "admin.dashboard.git_gc_repos_success" )
2020-01-20 23:01:19 +03:00
err = repo_module . GitGcRepos ( shutdownCtx )
2016-11-21 06:21:24 +03:00
case syncSSHAuthorizedKey :
2014-12-31 21:07:51 +03:00
success = ctx . Tr ( "admin.dashboard.resync_all_sshkeys_success" )
err = models . RewriteAllPublicKeys ( )
2016-11-21 06:21:24 +03:00
case syncRepositoryUpdateHook :
2017-02-23 06:40:44 +03:00
success = ctx . Tr ( "admin.dashboard.resync_all_hooks_success" )
2020-01-20 23:01:19 +03:00
err = repo_module . SyncRepositoryHooks ( shutdownCtx )
2016-11-21 06:21:24 +03:00
case reinitMissingRepository :
2016-02-04 20:51:00 +03:00
success = ctx . Tr ( "admin.dashboard.reinit_missing_repos_success" )
2020-01-20 23:01:19 +03:00
err = repo_module . ReinitMissingRepositories ( )
2017-05-10 16:10:18 +03:00
case syncExternalUsers :
success = ctx . Tr ( "admin.dashboard.sync_external_users_started" )
2019-12-15 12:51:28 +03:00
go graceful . GetManager ( ) . RunWithShutdownContext ( models . SyncExternalUsers )
2018-03-02 12:09:43 +03:00
case gitFsck :
success = ctx . Tr ( "admin.dashboard.git_fsck_started" )
2020-01-20 23:01:19 +03:00
err = repo_module . GitFsck ( shutdownCtx )
2019-06-02 09:40:12 +03:00
case deleteGeneratedRepositoryAvatars :
success = ctx . Tr ( "admin.dashboard.delete_generated_repository_avatars_success" )
err = models . RemoveRandomAvatars ( )
2014-05-06 21:47:47 +04:00
}
if err != nil {
ctx . Flash . Error ( err . Error ( ) )
} else {
ctx . Flash . Success ( success )
}
2016-11-27 13:14:25 +03:00
ctx . Redirect ( setting . AppSubURL + "/admin" )
2014-05-06 21:47:47 +04:00
return
}
2014-03-21 00:04:56 +04:00
ctx . Data [ "Stats" ] = models . GetStatistic ( )
2014-11-19 03:05:33 +03:00
// FIXME: update periodically
2014-03-22 15:42:24 +04:00
updateSystemStatus ( )
ctx . Data [ "SysStatus" ] = sysStatus
2016-11-21 06:21:24 +03:00
ctx . HTML ( 200 , tplDashboard )
2014-03-20 15:50:26 +04:00
}
2016-11-21 06:21:24 +03:00
// SendTestMail send test mail to confirm mail service is OK
2016-03-11 19:56:52 +03:00
func SendTestMail ( ctx * context . Context ) {
2016-02-25 07:59:17 +03:00
email := ctx . Query ( "email" )
// Send a test email to the user's email address and redirect back to Config
2019-09-24 08:02:49 +03:00
if err := mailer . SendTestMail ( email ) ; err != nil {
2016-02-25 07:59:17 +03:00
ctx . Flash . Error ( ctx . Tr ( "admin.config.test_mail_failed" , email , err ) )
} else {
ctx . Flash . Info ( ctx . Tr ( "admin.config.test_mail_sent" , email ) )
}
2016-02-19 01:13:12 +03:00
2016-11-27 13:14:25 +03:00
ctx . Redirect ( setting . AppSubURL + "/admin/config" )
2016-02-19 01:13:12 +03:00
}
2019-11-14 23:06:02 +03:00
func shadowPasswordKV ( cfgItem , splitter string ) string {
2019-06-26 19:12:38 +03:00
fields := strings . Split ( cfgItem , splitter )
for i := 0 ; i < len ( fields ) ; i ++ {
if strings . HasPrefix ( fields [ i ] , "password=" ) {
fields [ i ] = "password=******"
break
}
}
return strings . Join ( fields , splitter )
}
2019-11-14 23:06:02 +03:00
func shadowURL ( provider , cfgItem string ) string {
2019-06-26 19:12:38 +03:00
u , err := url . Parse ( cfgItem )
if err != nil {
2019-11-14 23:06:02 +03:00
log . Error ( "Shadowing Password for %v failed: %v" , provider , err )
2019-06-26 19:12:38 +03:00
return cfgItem
}
if u . User != nil {
atIdx := strings . Index ( cfgItem , "@" )
if atIdx > 0 {
colonIdx := strings . LastIndex ( cfgItem [ : atIdx ] , ":" )
if colonIdx > 0 {
return cfgItem [ : colonIdx + 1 ] + "******" + cfgItem [ atIdx : ]
}
}
}
return cfgItem
}
func shadowPassword ( provider , cfgItem string ) string {
switch provider {
case "redis" :
2019-11-14 23:06:02 +03:00
return shadowPasswordKV ( cfgItem , "," )
2019-06-26 19:12:38 +03:00
case "mysql" :
//root:@tcp(localhost:3306)/macaron?charset=utf8
atIdx := strings . Index ( cfgItem , "@" )
if atIdx > 0 {
colonIdx := strings . Index ( cfgItem [ : atIdx ] , ":" )
if colonIdx > 0 {
return cfgItem [ : colonIdx + 1 ] + "******" + cfgItem [ atIdx : ]
}
}
return cfgItem
case "postgres" :
// user=jiahuachen dbname=macaron port=5432 sslmode=disable
if ! strings . HasPrefix ( cfgItem , "postgres://" ) {
2019-11-14 23:06:02 +03:00
return shadowPasswordKV ( cfgItem , " " )
2019-06-26 19:12:38 +03:00
}
2019-11-14 23:06:02 +03:00
fallthrough
case "couchbase" :
return shadowURL ( provider , cfgItem )
2019-06-26 19:12:38 +03:00
// postgres://pqgotest:password@localhost/pqgotest?sslmode=verify-full
2019-11-14 23:06:02 +03:00
// Notice: use shadowURL
2019-06-26 19:12:38 +03:00
}
2019-11-14 23:06:02 +03:00
return cfgItem
2019-06-26 19:12:38 +03:00
}
2016-11-21 06:21:24 +03:00
// Config show admin config page
2016-03-11 19:56:52 +03:00
func Config ( ctx * context . Context ) {
2015-09-12 16:21:09 +03:00
ctx . Data [ "Title" ] = ctx . Tr ( "admin.config" )
2014-08-30 16:49:51 +04:00
ctx . Data [ "PageIsAdmin" ] = true
ctx . Data [ "PageIsAdminConfig" ] = true
2014-03-21 11:27:59 +04:00
2017-06-22 16:21:56 +03:00
ctx . Data [ "CustomConf" ] = setting . CustomConf
2016-11-27 13:14:25 +03:00
ctx . Data [ "AppUrl" ] = setting . AppURL
2014-05-26 04:11:25 +04:00
ctx . Data [ "Domain" ] = setting . Domain
ctx . Data [ "OfflineMode" ] = setting . OfflineMode
ctx . Data [ "DisableRouterLog" ] = setting . DisableRouterLog
ctx . Data [ "RunUser" ] = setting . RunUser
2014-07-26 08:24:27 +04:00
ctx . Data [ "RunMode" ] = strings . Title ( macaron . Env )
2019-05-15 04:57:00 +03:00
ctx . Data [ "GitVersion" ] , _ = git . BinVersion ( )
2014-05-26 04:11:25 +04:00
ctx . Data [ "RepoRootPath" ] = setting . RepoRootPath
2019-03-20 01:40:13 +03:00
ctx . Data [ "CustomRootPath" ] = setting . CustomPath
2014-05-28 09:53:06 +04:00
ctx . Data [ "StaticRootPath" ] = setting . StaticRootPath
ctx . Data [ "LogRootPath" ] = setting . LogRootPath
2014-05-26 04:11:25 +04:00
ctx . Data [ "ScriptType" ] = setting . ScriptType
2014-06-24 21:55:47 +04:00
ctx . Data [ "ReverseProxyAuthUser" ] = setting . ReverseProxyAuthUser
2018-12-18 20:05:48 +03:00
ctx . Data [ "ReverseProxyAuthEmail" ] = setting . ReverseProxyAuthEmail
2014-03-21 11:27:59 +04:00
2016-02-28 04:48:39 +03:00
ctx . Data [ "SSH" ] = setting . SSH
2019-06-16 21:24:49 +03:00
ctx . Data [ "LFS" ] = setting . LFS
2016-02-28 04:48:39 +03:00
2014-05-26 04:11:25 +04:00
ctx . Data [ "Service" ] = setting . Service
2019-08-24 12:24:45 +03:00
ctx . Data [ "DbCfg" ] = setting . Database
2015-02-11 05:06:59 +03:00
ctx . Data [ "Webhook" ] = setting . Webhook
2014-06-08 12:45:34 +04:00
2014-03-21 12:13:32 +04:00
ctx . Data [ "MailerEnabled" ] = false
2014-05-26 04:11:25 +04:00
if setting . MailService != nil {
2014-03-21 12:13:32 +04:00
ctx . Data [ "MailerEnabled" ] = true
2014-05-26 04:11:25 +04:00
ctx . Data [ "Mailer" ] = setting . MailService
2014-03-21 12:13:32 +04:00
}
2014-03-21 11:27:59 +04:00
2017-10-26 04:37:33 +03:00
ctx . Data [ "CacheAdapter" ] = setting . CacheService . Adapter
ctx . Data [ "CacheInterval" ] = setting . CacheService . Interval
2019-06-26 19:12:38 +03:00
ctx . Data [ "CacheConn" ] = shadowPassword ( setting . CacheService . Adapter , setting . CacheService . Conn )
2019-05-06 17:35:11 +03:00
ctx . Data [ "CacheItemTTL" ] = setting . CacheService . TTL
2014-03-21 18:09:57 +04:00
2019-06-26 19:12:38 +03:00
sessionCfg := setting . SessionConfig
2019-11-28 20:35:41 +03:00
if sessionCfg . Provider == "VirtualSession" {
var realSession session . Options
if err := json . Unmarshal ( [ ] byte ( sessionCfg . ProviderConfig ) , & realSession ) ; err != nil {
log . Error ( "Unable to unmarshall session config for virtualed provider config: %s\nError: %v" , sessionCfg . ProviderConfig , err )
}
2020-01-29 10:47:46 +03:00
sessionCfg . Provider = realSession . Provider
sessionCfg . ProviderConfig = realSession . ProviderConfig
sessionCfg . CookieName = realSession . CookieName
sessionCfg . CookiePath = realSession . CookiePath
sessionCfg . Gclifetime = realSession . Gclifetime
sessionCfg . Maxlifetime = realSession . Maxlifetime
sessionCfg . Secure = realSession . Secure
sessionCfg . Domain = realSession . Domain
2019-11-28 20:35:41 +03:00
}
2019-06-26 19:12:38 +03:00
sessionCfg . ProviderConfig = shadowPassword ( sessionCfg . Provider , sessionCfg . ProviderConfig )
ctx . Data [ "SessionConfig" ] = sessionCfg
2014-03-22 17:21:57 +04:00
2014-05-26 04:11:25 +04:00
ctx . Data [ "DisableGravatar" ] = setting . DisableGravatar
2016-08-07 20:27:38 +03:00
ctx . Data [ "EnableFederatedAvatar" ] = setting . EnableFederatedAvatar
2014-03-22 14:42:19 +04:00
2016-08-10 21:01:42 +03:00
ctx . Data [ "Git" ] = setting . Git
2019-03-20 01:40:13 +03:00
type envVar struct {
Name , Value string
}
envVars := map [ string ] * envVar { }
if len ( os . Getenv ( "GITEA_WORK_DIR" ) ) > 0 {
envVars [ "GITEA_WORK_DIR" ] = & envVar { "GITEA_WORK_DIR" , os . Getenv ( "GITEA_WORK_DIR" ) }
}
if len ( os . Getenv ( "GITEA_CUSTOM" ) ) > 0 {
envVars [ "GITEA_CUSTOM" ] = & envVar { "GITEA_CUSTOM" , os . Getenv ( "GITEA_CUSTOM" ) }
}
ctx . Data [ "EnvVars" ] = envVars
2019-04-02 10:48:31 +03:00
ctx . Data [ "Loggers" ] = setting . LogDescriptions
ctx . Data [ "RedirectMacaronLog" ] = setting . RedirectMacaronLog
ctx . Data [ "EnableAccessLog" ] = setting . EnableAccessLog
ctx . Data [ "AccessLogTemplate" ] = setting . AccessLogTemplate
ctx . Data [ "DisableRouterLog" ] = setting . DisableRouterLog
ctx . Data [ "EnableXORMLog" ] = setting . EnableXORMLog
2019-08-24 12:24:45 +03:00
ctx . Data [ "LogSQL" ] = setting . Database . LogSQL
2014-03-21 20:13:13 +04:00
2016-11-21 06:21:24 +03:00
ctx . HTML ( 200 , tplConfig )
2014-03-21 09:48:10 +04:00
}
2014-06-13 21:01:52 +04:00
2016-11-21 06:21:24 +03:00
// Monitor show admin monitor page
2016-03-11 19:56:52 +03:00
func Monitor ( ctx * context . Context ) {
2014-08-30 16:49:51 +04:00
ctx . Data [ "Title" ] = ctx . Tr ( "admin.monitor" )
ctx . Data [ "PageIsAdmin" ] = true
ctx . Data [ "PageIsAdminMonitor" ] = true
2019-11-30 17:40:22 +03:00
ctx . Data [ "Processes" ] = process . GetManager ( ) . Processes ( )
2015-08-17 21:19:29 +03:00
ctx . Data [ "Entries" ] = cron . ListTasks ( )
2020-01-07 14:23:09 +03:00
ctx . Data [ "Queues" ] = queue . GetManager ( ) . ManagedQueues ( )
2016-11-21 06:21:24 +03:00
ctx . HTML ( 200 , tplMonitor )
2014-06-13 21:01:52 +04:00
}
2019-11-30 17:40:22 +03:00
// MonitorCancel cancels a process
func MonitorCancel ( ctx * context . Context ) {
pid := ctx . ParamsInt64 ( "pid" )
process . GetManager ( ) . Cancel ( pid )
ctx . JSON ( 200 , map [ string ] interface { } {
"redirect" : ctx . Repo . RepoLink + "/admin/monitor" ,
} )
}
2020-01-07 14:23:09 +03:00
// Queue shows details for a specific queue
func Queue ( ctx * context . Context ) {
qid := ctx . ParamsInt64 ( "qid" )
mq := queue . GetManager ( ) . GetManagedQueue ( qid )
if mq == nil {
ctx . Status ( 404 )
return
}
ctx . Data [ "Title" ] = ctx . Tr ( "admin.monitor.queue" , mq . Name )
ctx . Data [ "PageIsAdmin" ] = true
ctx . Data [ "PageIsAdminMonitor" ] = true
ctx . Data [ "Queue" ] = mq
ctx . HTML ( 200 , tplQueue )
}
// WorkerCancel cancels a worker group
func WorkerCancel ( ctx * context . Context ) {
qid := ctx . ParamsInt64 ( "qid" )
mq := queue . GetManager ( ) . GetManagedQueue ( qid )
if mq == nil {
ctx . Status ( 404 )
return
}
pid := ctx . ParamsInt64 ( "pid" )
mq . CancelWorkers ( pid )
ctx . Flash . Info ( ctx . Tr ( "admin.monitor.queue.pool.cancelling" ) )
ctx . JSON ( 200 , map [ string ] interface { } {
"redirect" : setting . AppSubURL + fmt . Sprintf ( "/admin/monitor/queue/%d" , qid ) ,
} )
}
2020-01-29 04:01:06 +03:00
// Flush flushes a queue
func Flush ( ctx * context . Context ) {
qid := ctx . ParamsInt64 ( "qid" )
mq := queue . GetManager ( ) . GetManagedQueue ( qid )
if mq == nil {
ctx . Status ( 404 )
return
}
timeout , err := time . ParseDuration ( ctx . Query ( "timeout" ) )
if err != nil {
timeout = - 1
}
ctx . Flash . Info ( ctx . Tr ( "admin.monitor.queue.pool.flush.added" , mq . Name ) )
go func ( ) {
err := mq . Flush ( timeout )
if err != nil {
log . Error ( "Flushing failure for %s: Error %v" , mq . Name , err )
}
} ( )
ctx . Redirect ( setting . AppSubURL + fmt . Sprintf ( "/admin/monitor/queue/%d" , qid ) )
}
2020-01-07 14:23:09 +03:00
// AddWorkers adds workers to a worker group
func AddWorkers ( ctx * context . Context ) {
qid := ctx . ParamsInt64 ( "qid" )
mq := queue . GetManager ( ) . GetManagedQueue ( qid )
if mq == nil {
ctx . Status ( 404 )
return
}
number := ctx . QueryInt ( "number" )
if number < 1 {
ctx . Flash . Error ( ctx . Tr ( "admin.monitor.queue.pool.addworkers.mustnumbergreaterzero" ) )
ctx . Redirect ( setting . AppSubURL + fmt . Sprintf ( "/admin/monitor/queue/%d" , qid ) )
return
}
timeout , err := time . ParseDuration ( ctx . Query ( "timeout" ) )
if err != nil {
ctx . Flash . Error ( ctx . Tr ( "admin.monitor.queue.pool.addworkers.musttimeoutduration" ) )
ctx . Redirect ( setting . AppSubURL + fmt . Sprintf ( "/admin/monitor/queue/%d" , qid ) )
return
}
2020-01-29 04:01:06 +03:00
if _ , ok := mq . Managed . ( queue . ManagedPool ) ; ! ok {
2020-01-07 14:23:09 +03:00
ctx . Flash . Error ( ctx . Tr ( "admin.monitor.queue.pool.none" ) )
ctx . Redirect ( setting . AppSubURL + fmt . Sprintf ( "/admin/monitor/queue/%d" , qid ) )
return
}
mq . AddWorkers ( number , timeout )
ctx . Flash . Success ( ctx . Tr ( "admin.monitor.queue.pool.added" ) )
ctx . Redirect ( setting . AppSubURL + fmt . Sprintf ( "/admin/monitor/queue/%d" , qid ) )
}
// SetQueueSettings sets the maximum number of workers and other settings for this queue
func SetQueueSettings ( ctx * context . Context ) {
qid := ctx . ParamsInt64 ( "qid" )
mq := queue . GetManager ( ) . GetManagedQueue ( qid )
if mq == nil {
ctx . Status ( 404 )
return
}
2020-01-29 04:01:06 +03:00
if _ , ok := mq . Managed . ( queue . ManagedPool ) ; ! ok {
2020-01-07 14:23:09 +03:00
ctx . Flash . Error ( ctx . Tr ( "admin.monitor.queue.pool.none" ) )
ctx . Redirect ( setting . AppSubURL + fmt . Sprintf ( "/admin/monitor/queue/%d" , qid ) )
return
}
maxNumberStr := ctx . Query ( "max-number" )
numberStr := ctx . Query ( "number" )
timeoutStr := ctx . Query ( "timeout" )
var err error
var maxNumber , number int
var timeout time . Duration
if len ( maxNumberStr ) > 0 {
maxNumber , err = strconv . Atoi ( maxNumberStr )
if err != nil {
ctx . Flash . Error ( ctx . Tr ( "admin.monitor.queue.settings.maxnumberworkers.error" ) )
ctx . Redirect ( setting . AppSubURL + fmt . Sprintf ( "/admin/monitor/queue/%d" , qid ) )
return
}
if maxNumber < - 1 {
maxNumber = - 1
}
} else {
maxNumber = mq . MaxNumberOfWorkers ( )
}
if len ( numberStr ) > 0 {
number , err = strconv . Atoi ( numberStr )
if err != nil || number < 0 {
ctx . Flash . Error ( ctx . Tr ( "admin.monitor.queue.settings.numberworkers.error" ) )
ctx . Redirect ( setting . AppSubURL + fmt . Sprintf ( "/admin/monitor/queue/%d" , qid ) )
return
}
} else {
number = mq . BoostWorkers ( )
}
if len ( timeoutStr ) > 0 {
timeout , err = time . ParseDuration ( timeoutStr )
if err != nil {
ctx . Flash . Error ( ctx . Tr ( "admin.monitor.queue.settings.timeout.error" ) )
ctx . Redirect ( setting . AppSubURL + fmt . Sprintf ( "/admin/monitor/queue/%d" , qid ) )
return
}
} else {
2020-01-29 04:01:06 +03:00
timeout = mq . BoostTimeout ( )
2020-01-07 14:23:09 +03:00
}
2020-01-29 04:01:06 +03:00
mq . SetPoolSettings ( maxNumber , number , timeout )
2020-01-07 14:23:09 +03:00
ctx . Flash . Success ( ctx . Tr ( "admin.monitor.queue.settings.changed" ) )
ctx . Redirect ( setting . AppSubURL + fmt . Sprintf ( "/admin/monitor/queue/%d" , qid ) )
}