Previously, we would filter containers and images by name, which could be fail if the app was renamed or no longer was tagged "correctly" due to a rebuild. Now, we filter by label, ensuring an app is completely cleaned up on deletion. Also: - Move docker image cleanup from apps plugin to builder plugin: This isn't where it belongs - images should be cleaned up in a builder plugin (or the builders plugin) and not in the apps plugin, which has nothing to do with docker images anyways. - Remove the code from the scheduler plugin, as that will only do anything if the scheduler is enabled for the app. - Bypass image removal if there are no images to remove - Always delete app containers: The herokuish builder creates intermediate build containers - something that should be refactored - and ideally this gets run in that builder plugin, but keeping the logic here ensures we don't have code duplication. This is otherwise safe as it will be a no-op if there are no containers to clean up.
152 lines
4.1 KiB
Go
152 lines
4.1 KiB
Go
package builder
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/dokku/dokku/plugins/common"
|
|
"github.com/otiai10/copy"
|
|
)
|
|
|
|
// TriggerBuilderDetect outputs a manually selected builder for the app
|
|
func TriggerBuilderDetect(appName string) error {
|
|
if builder := common.PropertyGet("builder", appName, "selected"); builder != "" {
|
|
fmt.Println(builder)
|
|
return nil
|
|
}
|
|
|
|
if builder := common.PropertyGet("builder", "--global", "selected"); builder != "" {
|
|
fmt.Println(builder)
|
|
return nil
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// TriggerBuilderGetProperty writes the builder key to stdout for a given app container
|
|
func TriggerBuilderGetProperty(appName string, key string) error {
|
|
if key != "selected" && key != "build-dir" {
|
|
return errors.New("Invalid logs property specified")
|
|
}
|
|
|
|
fmt.Println(common.PropertyGet("builder", appName, key))
|
|
return nil
|
|
}
|
|
|
|
// TriggerBuilderImageIsCNB prints true if an image is cnb based, false otherwise
|
|
func TriggerBuilderImageIsCNB(appName string, image string) error {
|
|
if common.IsImageCnbBased(image) {
|
|
fmt.Println("true")
|
|
} else {
|
|
fmt.Println("false")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// TriggerBuilderImageIsHerokuish prints true if an image is herokuish based, false otherwise
|
|
func TriggerBuilderImageIsHerokuish(appName string, image string) error {
|
|
if common.IsImageHerokuishBased(image, appName) {
|
|
fmt.Println("true")
|
|
} else {
|
|
fmt.Println("false")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// TriggerCorePostExtract moves a configured build-dir to be in the app root dir
|
|
func TriggerCorePostExtract(appName string, sourceWorkDir string) error {
|
|
buildDir := strings.Trim(reportComputedBuildDir(appName), "/")
|
|
if buildDir == "" {
|
|
return nil
|
|
}
|
|
|
|
newSourceWorkDir := filepath.Join(sourceWorkDir, buildDir)
|
|
if !common.DirectoryExists(newSourceWorkDir) {
|
|
return fmt.Errorf("Specified build-dir not found in sourcecode working directory: %v", buildDir)
|
|
}
|
|
|
|
tmpWorkDir, err := ioutil.TempDir(os.TempDir(), fmt.Sprintf("dokku-%s-%s", common.MustGetEnv("DOKKU_PID"), "CorePostExtract"))
|
|
if err != nil {
|
|
return fmt.Errorf("Unable to create temporary working directory: %v", err.Error())
|
|
}
|
|
|
|
if err := removeAllContents(tmpWorkDir); err != nil {
|
|
return fmt.Errorf("Unable to clear out temporary working directory for rewrite: %v", err.Error())
|
|
}
|
|
|
|
if err := copy.Copy(newSourceWorkDir, tmpWorkDir); err != nil {
|
|
return fmt.Errorf("Unable to move build-dir to temporary working directory: %v", err.Error())
|
|
}
|
|
|
|
if err := removeAllContents(sourceWorkDir); err != nil {
|
|
return fmt.Errorf("Unable to clear out sourcecode working directory for rewrite: %v", err.Error())
|
|
}
|
|
|
|
if err := copy.Copy(tmpWorkDir, sourceWorkDir); err != nil {
|
|
return fmt.Errorf("Unable to move build-dir to sourcecode working directory: %v", err.Error())
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// TriggerInstall runs the install step for the builder plugin
|
|
func TriggerInstall() error {
|
|
if err := common.PropertySetup("builder"); err != nil {
|
|
return fmt.Errorf("Unable to install the builder plugin: %s", err.Error())
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// TriggerPostAppCloneSetup creates new builder files
|
|
func TriggerPostAppCloneSetup(oldAppName string, newAppName string) error {
|
|
err := common.PropertyClone("builder", oldAppName, newAppName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// TriggerPostAppRenameSetup renames builder files
|
|
func TriggerPostAppRenameSetup(oldAppName string, newAppName string) error {
|
|
if err := common.PropertyClone("builder", oldAppName, newAppName); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := common.PropertyDestroy("builder", oldAppName); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// TriggerPostDelete destroys the builder property for a given app container
|
|
func TriggerPostDelete(appName string) error {
|
|
if err := common.PropertyDestroy("builder", appName); err != nil {
|
|
return err
|
|
}
|
|
|
|
imagesByAppLabel, err := listImagesByAppLabel(appName)
|
|
if err != nil {
|
|
common.LogWarn(err.Error())
|
|
}
|
|
|
|
imageRepo := common.GetAppImageRepo(appName)
|
|
imagesByRepo, err := listImagesByImageRepo(imageRepo)
|
|
if err != nil {
|
|
common.LogWarn(err.Error())
|
|
}
|
|
|
|
images := append(imagesByAppLabel, imagesByRepo...)
|
|
common.RemoveImages(images)
|
|
|
|
return nil
|
|
}
|