Files
dokku/plugins/builder/triggers.go
Jose Diaz-Gonzalez 5dc2f20432 fix: remove all containers and images by label on app destroy
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.
2023-08-05 10:58:57 -04:00

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
}