2020-11-01 15:53:53 -05:00
|
|
|
package ps
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
2020-11-21 20:56:59 -05:00
|
|
|
"path/filepath"
|
2020-11-01 15:53:53 -05:00
|
|
|
|
|
|
|
|
dockeroptions "github.com/dokku/dokku/plugins/docker-options"
|
|
|
|
|
|
|
|
|
|
"github.com/dokku/dokku/plugins/common"
|
2020-11-21 20:56:59 -05:00
|
|
|
"github.com/gofrs/flock"
|
2020-11-01 15:53:53 -05:00
|
|
|
)
|
|
|
|
|
|
2020-11-18 13:24:43 -05:00
|
|
|
// CommandInspect displays a sanitized version of docker inspect for an app
|
2020-11-01 15:53:53 -05:00
|
|
|
func CommandInspect(appName string) error {
|
|
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scheduler := common.GetAppScheduler(appName)
|
|
|
|
|
return common.PlugnTrigger("scheduler-inspect", []string{scheduler, appName}...)
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-18 13:24:43 -05:00
|
|
|
// CommandRebuild rebuilds an app from source
|
2020-11-21 17:31:13 -05:00
|
|
|
func CommandRebuild(appName string, allApps bool, parallelCount int) error {
|
2020-11-01 15:53:53 -05:00
|
|
|
if allApps {
|
2020-11-21 19:36:13 -05:00
|
|
|
return common.RunCommandAgainstAllApps(Rebuild, "rebuild", parallelCount)
|
2020-11-01 15:53:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Rebuild(appName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CommandReport displays a ps report for one or more apps
|
2021-02-01 22:23:05 -05:00
|
|
|
func CommandReport(appName string, format string, infoFlag string) error {
|
2020-11-01 15:53:53 -05:00
|
|
|
if len(appName) == 0 {
|
|
|
|
|
apps, err := common.DokkuApps()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
for _, appName := range apps {
|
2021-02-01 22:23:05 -05:00
|
|
|
if err := ReportSingleApp(appName, format, infoFlag); err != nil {
|
2020-11-01 15:53:53 -05:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-01 22:23:05 -05:00
|
|
|
return ReportSingleApp(appName, format, infoFlag)
|
2020-11-01 15:53:53 -05:00
|
|
|
}
|
|
|
|
|
|
2020-11-18 13:24:43 -05:00
|
|
|
// CommandRestart restarts an app
|
2020-11-21 17:31:13 -05:00
|
|
|
func CommandRestart(appName string, allApps bool, parallelCount int) error {
|
2020-11-01 15:53:53 -05:00
|
|
|
if allApps {
|
2020-11-21 19:36:13 -05:00
|
|
|
return common.RunCommandAgainstAllApps(Restart, "restart", parallelCount)
|
2020-11-01 15:53:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Restart(appName)
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-18 13:24:43 -05:00
|
|
|
// CommandRestore starts previously running apps e.g. after reboot
|
2020-11-21 20:37:54 -05:00
|
|
|
func CommandRestore(appName string, allApps bool, parallelCount int) error {
|
|
|
|
|
if allApps {
|
2020-11-21 21:07:20 -05:00
|
|
|
if err := restorePrep(); err != nil {
|
2020-11-21 20:37:54 -05:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return common.RunCommandAgainstAllApps(Restore, "restore", parallelCount)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if appName == "" {
|
|
|
|
|
common.LogWarn("Restore specified without app, assuming --all")
|
|
|
|
|
|
2020-11-21 21:07:20 -05:00
|
|
|
if err := restorePrep(); err != nil {
|
2020-11-21 20:37:54 -05:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
return common.RunCommandAgainstAllApps(Restore, "restore", parallelCount)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Restore(appName)
|
2020-11-01 15:53:53 -05:00
|
|
|
}
|
|
|
|
|
|
2020-11-18 13:24:43 -05:00
|
|
|
// CommandRetire ensures old containers are retired
|
2020-11-01 15:53:53 -05:00
|
|
|
func CommandRetire() error {
|
2020-11-21 20:56:59 -05:00
|
|
|
lockFile := filepath.Join(common.MustGetEnv("DOKKU_LIB_ROOT"), "data", "ps", "retire")
|
|
|
|
|
scheduler := common.GetGlobalScheduler()
|
|
|
|
|
|
|
|
|
|
fileLock := flock.New(lockFile)
|
|
|
|
|
locked, err := fileLock.TryLock()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("Failed to acquire ps:retire lock: %s", err)
|
|
|
|
|
}
|
|
|
|
|
defer fileLock.Unlock()
|
|
|
|
|
|
|
|
|
|
if !locked {
|
|
|
|
|
return fmt.Errorf("Failed to acquire ps:retire lock")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := common.PlugnTrigger("scheduler-retire", []string{scheduler}...); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-01 15:53:53 -05:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-18 13:24:43 -05:00
|
|
|
// CommandScale gets or sets how many instances of a given process to run
|
2020-11-18 01:23:36 -05:00
|
|
|
func CommandScale(appName string, skipDeploy bool, processTuples []string) error {
|
2020-11-01 15:53:53 -05:00
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
procfilePath := getProcfilePath(appName)
|
2020-11-23 00:11:10 -05:00
|
|
|
if !hasScaleFile(appName) || common.FileExists(procfilePath) {
|
|
|
|
|
update := func() error {
|
2020-11-18 12:28:44 -05:00
|
|
|
return updateScalefile(appName, make(map[string]int))
|
2020-11-01 15:53:53 -05:00
|
|
|
}
|
2020-11-23 00:11:10 -05:00
|
|
|
if err := common.SuppressOutput(update); err != nil {
|
2020-11-01 15:53:53 -05:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(processTuples) == 0 {
|
2020-11-18 00:33:01 -05:00
|
|
|
return scaleReport(appName)
|
2020-11-01 15:53:53 -05:00
|
|
|
}
|
|
|
|
|
|
2021-08-01 16:07:55 -04:00
|
|
|
if !canScaleApp(appName) {
|
|
|
|
|
return fmt.Errorf("App %s contains DOKKU_SCALE file and cannot be manually scaled", appName)
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-18 01:23:36 -05:00
|
|
|
return scaleSet(appName, skipDeploy, processTuples)
|
2020-11-01 15:53:53 -05:00
|
|
|
}
|
|
|
|
|
|
2020-11-18 13:24:43 -05:00
|
|
|
// CommandSet sets or clears a ps property for an app
|
2020-11-01 15:53:53 -05:00
|
|
|
func CommandSet(appName string, property string, value string) error {
|
|
|
|
|
if property == "restart-policy" {
|
|
|
|
|
if !isValidRestartPolicy(value) {
|
|
|
|
|
return errors.New("Invalid restart-policy specified")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
common.LogInfo2Quiet(fmt.Sprintf("Setting %s to %s", property, value))
|
|
|
|
|
return dockeroptions.SetDockerOptionForPhases(appName, []string{"deploy"}, "restart", value)
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-04 00:50:14 -05:00
|
|
|
common.CommandPropertySet("ps", appName, property, value, DefaultProperties, GlobalProperties)
|
2020-11-01 15:53:53 -05:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-18 13:24:43 -05:00
|
|
|
// CommandStart starts an app
|
2020-11-21 17:31:13 -05:00
|
|
|
func CommandStart(appName string, allApps bool, parallelCount int) error {
|
2020-11-01 15:53:53 -05:00
|
|
|
if allApps {
|
2020-11-21 19:36:13 -05:00
|
|
|
return common.RunCommandAgainstAllApps(Start, "start", parallelCount)
|
2020-11-01 15:53:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Start(appName)
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-18 13:24:43 -05:00
|
|
|
// CommandStop stops an app
|
2020-11-21 17:31:13 -05:00
|
|
|
func CommandStop(appName string, allApps bool, parallelCount int) error {
|
2020-11-01 15:53:53 -05:00
|
|
|
if allApps {
|
2020-11-21 19:36:13 -05:00
|
|
|
return common.RunCommandAgainstAllApps(Stop, "stop", parallelCount)
|
2020-11-01 15:53:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Stop(appName)
|
|
|
|
|
}
|