mirror of
https://github.com/dokku/dokku.git
synced 2026-07-11 04:51:57 +02:00
The `ps:scale` command now accepts a `--format` flag that defaults to `stdout` and can be set to `json` to emit the current formation as a JSON array of process type and quantity objects, matching the JSON output the `:report` subcommands already provide. The flag only applies when displaying the current formation; it is ignored when process types are supplied for scaling. When no scale has been set for the app, the JSON output is an empty array.
219 lines
5.4 KiB
Go
219 lines
5.4 KiB
Go
package ps
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/dokku/dokku/plugins/common"
|
|
"github.com/gofrs/flock"
|
|
)
|
|
|
|
// CommandInspect displays a sanitized version of docker inspect for an app
|
|
func CommandInspect(appName string) error {
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
return err
|
|
}
|
|
|
|
scheduler := common.GetAppScheduler(appName)
|
|
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
|
Trigger: "scheduler-inspect",
|
|
Args: []string{scheduler, appName},
|
|
StreamStdio: true,
|
|
})
|
|
return err
|
|
}
|
|
|
|
// CommandRebuild rebuilds an app from source
|
|
func CommandRebuild(appName string, allApps bool, parallelCount int) error {
|
|
if allApps {
|
|
return common.RunCommandAgainstAllApps(Rebuild, "rebuild", parallelCount)
|
|
}
|
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
return err
|
|
}
|
|
|
|
return Rebuild(appName)
|
|
}
|
|
|
|
// CommandReport displays a ps report for one or more apps
|
|
func CommandReport(appName string, format string, infoFlag string) error {
|
|
if len(appName) == 0 {
|
|
apps, err := common.DokkuApps()
|
|
if err != nil {
|
|
if errors.Is(err, common.NoAppsExist) {
|
|
common.LogWarn(err.Error())
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
for _, appName := range apps {
|
|
if err := ReportSingleApp(appName, format, infoFlag); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
return ReportSingleApp(appName, format, infoFlag)
|
|
}
|
|
|
|
// CommandRestart restarts an app
|
|
func CommandRestart(appName string, processName string, allApps bool, parallelCount int) error {
|
|
if allApps {
|
|
if processName != "" {
|
|
return errors.New("Unable to restart all apps when specifying a process name")
|
|
}
|
|
return common.RunCommandAgainstAllApps(Restart, "restart", parallelCount)
|
|
}
|
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
return err
|
|
}
|
|
|
|
if processName != "" {
|
|
return RestartProcess(appName, processName)
|
|
}
|
|
|
|
return Restart(appName)
|
|
}
|
|
|
|
// CommandRestore starts previously running apps e.g. after reboot
|
|
func CommandRestore(appName string, allApps bool, parallelCount int) error {
|
|
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
|
Trigger: "pre-restore",
|
|
StreamStdio: true,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("Error running pre-restore: %s", err)
|
|
}
|
|
|
|
if allApps {
|
|
if err := restorePrep(); err != nil {
|
|
return err
|
|
}
|
|
|
|
return common.RunCommandAgainstAllApps(Restore, "restore", parallelCount)
|
|
}
|
|
|
|
if appName == "" {
|
|
common.LogWarn("Restore specified without app, assuming --all")
|
|
|
|
if err := restorePrep(); err != nil {
|
|
return err
|
|
}
|
|
return common.RunCommandAgainstAllApps(Restore, "restore", parallelCount)
|
|
}
|
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
return err
|
|
}
|
|
|
|
return Restore(appName)
|
|
}
|
|
|
|
// CommandRetire ensures old containers are retired
|
|
func CommandRetire(appName string) error {
|
|
lockFile := filepath.Join(common.GetDataDirectory("ps"), "retire")
|
|
scheduler := ""
|
|
if appName == "" {
|
|
scheduler = common.GetGlobalScheduler()
|
|
} else {
|
|
scheduler = common.GetAppScheduler(appName)
|
|
}
|
|
|
|
fileLock := flock.New(lockFile)
|
|
locked, err := fileLock.TryLock()
|
|
if err != nil {
|
|
return &RetireLockFailed{&err}
|
|
}
|
|
defer fileLock.Unlock()
|
|
|
|
if !locked {
|
|
return &RetireLockFailed{}
|
|
}
|
|
|
|
common.LogInfo1("Retiring old containers and images")
|
|
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
|
Trigger: "scheduler-retire",
|
|
Args: []string{scheduler, appName},
|
|
StreamStdio: true,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("Error retiring containers: %w", err)
|
|
}
|
|
|
|
common.LogInfo1("Retiring expired run containers")
|
|
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
|
Trigger: "scheduler-run-retire",
|
|
StreamStdio: true,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("Error retiring expired run containers: %w", err)
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
// CommandScale gets or sets how many instances of a given process to run
|
|
func CommandScale(appName string, skipDeploy bool, format string, processTuples []string) error {
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(processTuples) == 0 {
|
|
return scaleReport(appName, format)
|
|
}
|
|
|
|
if !canScaleApp(appName) {
|
|
return fmt.Errorf("App %s contains an app.json file with a formations key and cannot be manually scaled", appName)
|
|
}
|
|
|
|
common.LogInfo1(fmt.Sprintf("Scaling %s processes: %s", appName, strings.Join(processTuples, " ")))
|
|
return scaleSet(scaleSetInput{
|
|
appName: appName,
|
|
skipDeploy: skipDeploy,
|
|
clearExisting: false,
|
|
processTuples: processTuples,
|
|
deployOnlyChanged: true,
|
|
})
|
|
}
|
|
|
|
// CommandSet sets or clears a ps property for an app
|
|
func CommandSet(appName string, property string, value string) error {
|
|
if property == "restart-policy" && value != "" && !isValidRestartPolicy(value) {
|
|
return errors.New("Invalid restart-policy specified")
|
|
}
|
|
|
|
common.CommandPropertySet("ps", appName, property, value, DefaultProperties, GlobalProperties)
|
|
return nil
|
|
}
|
|
|
|
// CommandStart starts an app
|
|
func CommandStart(appName string, allApps bool, parallelCount int) error {
|
|
if allApps {
|
|
return common.RunCommandAgainstAllApps(Start, "start", parallelCount)
|
|
}
|
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
return err
|
|
}
|
|
|
|
return Start(appName)
|
|
}
|
|
|
|
// CommandStop stops an app
|
|
func CommandStop(appName string, allApps bool, parallelCount int) error {
|
|
if allApps {
|
|
return common.RunCommandAgainstAllApps(Stop, "stop", parallelCount)
|
|
}
|
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
return err
|
|
}
|
|
|
|
return Stop(appName)
|
|
}
|