diff --git a/plugins/app-json/appjson.go b/plugins/app-json/appjson.go index 8d064210d..4d8aad640 100644 --- a/plugins/app-json/appjson.go +++ b/plugins/app-json/appjson.go @@ -20,8 +20,9 @@ var ( // AppJSON is a struct that represents an app.json file as understood by Dokku type AppJSON struct { - Cron []CronCommand `json:"cron"` - Scripts struct { + Cron []CronCommand `json:"cron"` + Formation map[string]Formation `json:"formation"` + Scripts struct { Dokku struct { Predeploy string `json:"predeploy"` Postdeploy string `json:"postdeploy"` @@ -36,6 +37,10 @@ type CronCommand struct { Schedule string `json:"schedule"` } +type Formation struct { + Quantity int `json:"quantity"` +} + // GetAppjsonDirectory returns the directory containing a given app's extracted app.json file func GetAppjsonDirectory(appName string) string { return filepath.Join(common.MustGetEnv("DOKKU_LIB_ROOT"), "data", "app-json", appName) diff --git a/plugins/app-json/functions.go b/plugins/app-json/functions.go index e393f0133..e370382a3 100644 --- a/plugins/app-json/functions.go +++ b/plugins/app-json/functions.go @@ -79,24 +79,33 @@ func constructScript(command string, shell string, isHerokuishImage bool, isCnbI return []string{shell, "-c", strings.Join(script, " ")} } -// getPhaseScript extracts app.json from app image and returns the appropriate json key/value -func getPhaseScript(appName string, phase string) (string, error) { +func getAppJson(appName string) (AppJSON, error) { if !common.FileExists(GetAppjsonPath(appName)) { - return "", nil + return AppJSON{}, nil } b, err := ioutil.ReadFile(GetAppjsonPath(appName)) if err != nil { - return "", fmt.Errorf("Cannot read app.json file: %v", err) + return AppJSON{}, fmt.Errorf("Cannot read app.json file: %v", err) } if strings.TrimSpace(string(b)) == "" { - return "", nil + return AppJSON{}, nil } var appJSON AppJSON if err = json.Unmarshal(b, &appJSON); err != nil { - return "", fmt.Errorf("Cannot parse app.json: %v", err) + return AppJSON{}, fmt.Errorf("Cannot parse app.json: %v", err) + } + + return AppJSON{}, nil +} + +// getPhaseScript extracts app.json from app image and returns the appropriate json key/value +func getPhaseScript(appName string, phase string) (string, error) { + appJSON, err := getAppJson(appName) + if err != nil { + return "", err } if phase == "heroku.postdeploy" { @@ -475,3 +484,29 @@ func refreshAppJSON(appName string, image string) error { common.CopyFromImage(appName, image, reportComputedAppjsonpath(appName), appjsonPath) return nil } + +func setScale(appName string, image string) error { + appJSON, err := getAppJson(appName) + if err != nil { + return err + } + + args := []string{appName} + for processType, formation := range appJSON.Formation { + args = append(args, fmt.Sprintf("%s=%d", processType, formation.Quantity)) + } + + if len(args) == 1 { + return common.PlugnTrigger("ps-can-scale", []string{appName, "true"}...) + } + + if err := common.PlugnTrigger("ps-can-scale", []string{appName, "false"}...); err != nil { + return err + } + + if err := common.PlugnTrigger("ps-scale-set", args...); err != nil { + return err + } + + return nil +} diff --git a/plugins/app-json/triggers.go b/plugins/app-json/triggers.go index c3ccc05b5..708a5583b 100644 --- a/plugins/app-json/triggers.go +++ b/plugins/app-json/triggers.go @@ -64,6 +64,10 @@ func TriggerPreDeploy(appName string, imageTag string) error { return err } + if err := setScale(appName, image); err != nil { + return err + } + if common.PropertyGet("common", appName, "deployed") == "true" { return nil }