Files
dokku/plugins/apps/functions.go
Jose Diaz-Gonzalez d7b23b84f0 fix: allow renaming old applications to new format
0.22.0 changed allowed values for app names, making it more difficult for users to fix their app names - you need to either downgrade+rename or recreate the app. The `apps:rename`  command can now rename these old applications to the new standard.

Also drop some app name verification from internal commands. Duplicate verification doesn't help much, and though it isn't excessively slow, it does prevent us from running commands against old apps that exist.

Refs #4267
2020-12-22 13:29:32 -05:00

164 lines
4.0 KiB
Go

package apps
import (
"bytes"
"errors"
"fmt"
"os"
"strings"
"github.com/dokku/dokku/plugins/common"
)
// checks if an app exists
func appExists(appName string) error {
if err := common.IsValidAppName(appName); err != nil {
return err
}
if !common.DirectoryExists(common.AppRoot(appName)) {
return fmt.Errorf("App %s does not exist", appName)
}
return nil
}
// checks if an app is locked
func appIsLocked(appName string) bool {
lockfilePath := fmt.Sprintf("%v/.deploy.lock", common.AppRoot(appName))
_, err := os.Stat(lockfilePath)
return !os.IsNotExist(err)
}
// verifies app name and creates an app
func createApp(appName string) error {
if err := common.IsValidAppName(appName); err != nil {
return err
}
if err := appExists(appName); err == nil {
return errors.New("Name is already taken")
}
common.LogInfo1Quiet(fmt.Sprintf("Creating %s...", appName))
os.MkdirAll(common.AppRoot(appName), 0755)
if err := common.PlugnTrigger("post-create", []string{appName}...); err != nil {
return err
}
return nil
}
// destroys an app
func destroyApp(appName string) error {
if err := common.VerifyAppName(appName); err != nil {
return err
}
if os.Getenv("DOKKU_APPS_FORCE_DELETE") != "1" {
if err := common.AskForDestructiveConfirmation(appName, "app"); err != nil {
return err
}
}
common.LogInfo1(fmt.Sprintf("Destroying %s (including all add-ons)", appName))
imageTag, _ := common.GetRunningImageTag(appName)
if err := common.PlugnTrigger("pre-delete", []string{appName, imageTag}...); err != nil {
return err
}
scheduler := common.GetAppScheduler(appName)
removeContainers := "true"
if err := common.PlugnTrigger("scheduler-stop", []string{scheduler, appName, removeContainers}...); err != nil {
return err
}
if err := common.PlugnTrigger("scheduler-post-delete", []string{scheduler, appName, imageTag}...); err != nil {
return err
}
if err := common.PlugnTrigger("post-delete", []string{appName, imageTag}...); err != nil {
return err
}
forceCleanup := true
common.DockerCleanup(appName, forceCleanup)
// remove contents for apps that are symlinks to other folders
if err := os.RemoveAll(fmt.Sprintf("%v/", common.AppRoot(appName))); err != nil {
common.LogWarn(err.Error())
}
// then remove the folder and/or the symlink
if err := os.RemoveAll(common.AppRoot(appName)); err != nil {
common.LogWarn(err.Error())
}
return nil
}
func listImagesByAppLabel(appName string) ([]string, error) {
command := []string{
common.DockerBin(),
"image",
"list",
"--quiet",
"--filter",
fmt.Sprintf("label=com.dokku.app-name=%v", appName),
}
var stderr bytes.Buffer
listCmd := common.NewShellCmd(strings.Join(command, " "))
listCmd.ShowOutput = false
listCmd.Command.Stderr = &stderr
b, err := listCmd.Output()
if err != nil {
return []string{}, errors.New(strings.TrimSpace(stderr.String()))
}
output := strings.Split(strings.TrimSpace(string(b[:])), "\n")
return output, nil
}
func listImagesByImageRepo(imageRepo string) ([]string, error) {
command := []string{
common.DockerBin(),
"image",
"list",
"--quiet",
imageRepo,
}
var stderr bytes.Buffer
listCmd := common.NewShellCmd(strings.Join(command, " "))
listCmd.ShowOutput = false
listCmd.Command.Stderr = &stderr
b, err := listCmd.Output()
if err != nil {
return []string{}, errors.New(strings.TrimSpace(stderr.String()))
}
output := strings.Split(strings.TrimSpace(string(b[:])), "\n")
return output, nil
}
// creates an app if allowed
func maybeCreateApp(appName string) error {
if err := appExists(appName); err == nil {
return nil
}
b, _ := common.PlugnTriggerOutput("config-get-global", []string{"DOKKU_DISABLE_APP_AUTOCREATION"}...)
disableAutocreate := strings.TrimSpace(string(b[:]))
if disableAutocreate == "true" {
common.LogWarn("App auto-creation disabled.")
return fmt.Errorf("Re-enable app auto-creation or create an app with 'dokku apps:create %s'", appName)
}
return common.SuppressOutput(func() error {
return createApp(appName)
})
}