refactor: move app.json extraction up to core-post-extract
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
# 0.30.0 Migration Guide
|
||||
|
||||
## Changes
|
||||
|
||||
- The `app.json` file is now extracted from the source code instead of the built image. For deploys via `git:from-image`, the file is extracted from the built image.
|
||||
|
||||
## Removals
|
||||
|
||||
- Support for [SPDY](https://en.wikipedia.org/wiki/SPDY) has been removed. No major browser supports it as of 2021. Custom `nginx.conf.sigil` templates referencing spdy-related variables will continue to build until the 1.0.0 release.
|
||||
|
||||
@@ -48,7 +48,7 @@ func GetAppjsonDirectory(appName string) string {
|
||||
return common.GetAppDataDirectory("app-json", appName)
|
||||
}
|
||||
|
||||
// GetAppjsonPath returns the path to a given app's extracted app.json file
|
||||
// GetAppjsonPath returns the path to a given app's extracted app.json file for use by other plugins
|
||||
func GetAppjsonPath(appName string) string {
|
||||
return filepath.Join(GetAppjsonDirectory(appName), "app.json")
|
||||
return getProcessSpecificAppJSONPath(appName)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -80,11 +81,11 @@ func constructScript(command string, shell string, isHerokuishImage bool, isCnbI
|
||||
}
|
||||
|
||||
func getAppJSON(appName string) (AppJSON, error) {
|
||||
if !common.FileExists(GetAppjsonPath(appName)) {
|
||||
if !hasAppJSON(appName) {
|
||||
return AppJSON{}, nil
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadFile(GetAppjsonPath(appName))
|
||||
b, err := ioutil.ReadFile(getProcessSpecificAppJSONPath(appName))
|
||||
if err != nil {
|
||||
return AppJSON{}, fmt.Errorf("Cannot read app.json file: %v", err)
|
||||
}
|
||||
@@ -101,6 +102,21 @@ func getAppJSON(appName string) (AppJSON, error) {
|
||||
return appJSON, nil
|
||||
}
|
||||
|
||||
func getAppJSONPath(appName string) string {
|
||||
directory := filepath.Join(common.MustGetEnv("DOKKU_LIB_ROOT"), "data", "app-json", appName)
|
||||
return filepath.Join(directory, "app.json")
|
||||
}
|
||||
|
||||
func getProcessSpecificAppJSONPath(appName string) string {
|
||||
existingAppJSON := getAppJSONPath(appName)
|
||||
processSpecificAppJSON := fmt.Sprintf("%s.%s", existingAppJSON, os.Getenv("DOKKU_PID"))
|
||||
if common.FileExists(processSpecificAppJSON) {
|
||||
return processSpecificAppJSON
|
||||
}
|
||||
|
||||
return existingAppJSON
|
||||
}
|
||||
|
||||
// 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)
|
||||
@@ -155,6 +171,19 @@ func getDokkuAppShell(appName string) string {
|
||||
return shell
|
||||
}
|
||||
|
||||
func hasAppJSON(appName string) bool {
|
||||
appJSONPath := getAppJSONPath(appName)
|
||||
if common.FileExists(fmt.Sprintf("%s.%s.missing", appJSONPath, os.Getenv("DOKKU_PID"))) {
|
||||
return false
|
||||
}
|
||||
|
||||
if common.FileExists(fmt.Sprintf("%s.%s", appJSONPath, os.Getenv("DOKKU_PID"))) {
|
||||
return true
|
||||
}
|
||||
|
||||
return common.FileExists(appJSONPath)
|
||||
}
|
||||
|
||||
func cleanupDeploymentContainer(appName string, containerID string, phase string) error {
|
||||
if phase != "predeploy" {
|
||||
os.Setenv("DOKKU_SKIP_IMAGE_RETIRE", "true")
|
||||
@@ -453,30 +482,6 @@ func createdContainerID(appName string, dockerArgs []string, image string, comma
|
||||
return containerID, err
|
||||
}
|
||||
|
||||
func refreshAppJSON(appName string, image string) error {
|
||||
baseDirectory := common.GetDataDirectory("app-json")
|
||||
if !common.DirectoryExists(baseDirectory) {
|
||||
return errors.New("Run 'dokku plugin:install' to ensure the correct directories exist")
|
||||
}
|
||||
|
||||
directory := common.GetAppDataDirectory("app-json", appName)
|
||||
if !common.DirectoryExists(directory) {
|
||||
if err := os.MkdirAll(directory, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
appjsonPath := GetAppjsonPath(appName)
|
||||
if common.FileExists(appjsonPath) {
|
||||
if err := os.Remove(appjsonPath); err != nil {
|
||||
return errors.New("Unable to remove previous app.json file")
|
||||
}
|
||||
}
|
||||
|
||||
common.CopyFromImage(appName, image, reportComputedAppjsonpath(appName), appjsonPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
func setScale(appName string, image string) error {
|
||||
appJSON, err := getAppJSON(appName)
|
||||
if err != nil {
|
||||
|
||||
@@ -3,8 +3,12 @@ package appjson
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
"github.com/otiai10/copy"
|
||||
)
|
||||
|
||||
// TriggerAppJSONProcessDeployParallelism returns the max number of processes to deploy in parallel
|
||||
@@ -33,6 +37,83 @@ func TriggerAppJSONProcessDeployParallelism(appName string, processType string)
|
||||
return nil
|
||||
}
|
||||
|
||||
// TriggerCorePostDeploy sets a property to
|
||||
// allow the app to be restored on boot
|
||||
func TriggerCorePostDeploy(appName string) error {
|
||||
existingAppJSON := getAppJSONPath(appName)
|
||||
processSpecificAppJSON := fmt.Sprintf("%s.%s", existingAppJSON, os.Getenv("DOKKU_PID"))
|
||||
if common.FileExists(processSpecificAppJSON) {
|
||||
if err := os.Rename(processSpecificAppJSON, existingAppJSON); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if common.FileExists(fmt.Sprintf("%s.missing", processSpecificAppJSON)) {
|
||||
if err := os.Remove(fmt.Sprintf("%s.missing", processSpecificAppJSON)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if common.FileExists(existingAppJSON) {
|
||||
if err := os.Remove(existingAppJSON); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TriggerCorePostExtract ensures that the main app.json is the one specified by app-json-path
|
||||
func TriggerCorePostExtract(appName string, sourceWorkDir string) error {
|
||||
appJSONPath := strings.Trim(reportComputedAppjsonpath(appName), "/")
|
||||
if appJSONPath == "" {
|
||||
appJSONPath = "app.json"
|
||||
}
|
||||
|
||||
existingAppJSON := getAppJSONPath(appName)
|
||||
files, err := filepath.Glob(fmt.Sprintf("%s.*", existingAppJSON))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, f := range files {
|
||||
if err := os.Remove(f); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
processSpecificAppJSON := fmt.Sprintf("%s.%s", existingAppJSON, os.Getenv("DOKKU_PID"))
|
||||
b, _ := common.PlugnTriggerOutput("git-get-property", []string{appName, "source-image"}...)
|
||||
appSourceImage := strings.TrimSpace(string(b[:]))
|
||||
|
||||
repoDefaultAppJSONPath := path.Join(sourceWorkDir, "app.json")
|
||||
if appSourceImage == "" {
|
||||
repoAppJSONPath := path.Join(sourceWorkDir, appJSONPath)
|
||||
if !common.FileExists(repoAppJSONPath) {
|
||||
if appJSONPath != "app.json" && common.FileExists(repoDefaultAppJSONPath) {
|
||||
if err := os.Remove(repoDefaultAppJSONPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return common.TouchFile(fmt.Sprintf("%s.missing", processSpecificAppJSON))
|
||||
}
|
||||
|
||||
if err := copy.Copy(repoAppJSONPath, processSpecificAppJSON); err != nil {
|
||||
return fmt.Errorf("Unable to extract app.json: %v", err.Error())
|
||||
}
|
||||
|
||||
if appJSONPath != "app.json" {
|
||||
if err := copy.Copy(repoAppJSONPath, repoDefaultAppJSONPath); err != nil {
|
||||
return fmt.Errorf("Unable to move app.json into place: %v", err.Error())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err := common.CopyFromImage(appName, appSourceImage, appJSONPath, processSpecificAppJSON); err != nil {
|
||||
return common.TouchFile(fmt.Sprintf("%s.missing", processSpecificAppJSON))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add validation to app.json file by ensuring it can be deserialized
|
||||
return nil
|
||||
}
|
||||
|
||||
// TriggerInstall initializes app-json directory structures
|
||||
func TriggerInstall() error {
|
||||
if err := common.PropertySetup("app-json"); err != nil {
|
||||
@@ -104,10 +185,6 @@ func TriggerPostDeploy(appName string, imageTag string) error {
|
||||
// TriggerPreDeploy is a trigger to execute predeploy and release deployment tasks
|
||||
func TriggerPreDeploy(appName string, imageTag string) error {
|
||||
image := common.GetAppImageName(appName, imageTag, "")
|
||||
if err := refreshAppJSON(appName, image); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := executeScript(appName, image, imageTag, "predeploy"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user