这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/appendices/0.31.0-migration-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 0.30.0 Migration Guide

## Changes

- Herokuish build cache is now mounted from a docker volume - eg. `cache-node-js-app` - instead of the local filesystem. All existing app cache will be cleared upon upgrading past 0.29.0.
1 change: 1 addition & 0 deletions docs/getting-started/upgrading/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Docker releases updates periodically to their engine. We recommend reading their

Before upgrading, check the migration guides to get comfortable with new features and prepare your deployment to be upgraded.

- [Upgrading to 0.31](/docs/appendices/0.31.0-migration-guide.md)
- [Upgrading to 0.30](/docs/appendices/0.30.0-migration-guide.md)
- [Upgrading to 0.29](/docs/appendices/0.29.0-migration-guide.md)
- [Upgrading to 0.28](/docs/appendices/0.28.0-migration-guide.md)
Expand Down
20 changes: 12 additions & 8 deletions plugins/builder-herokuish/builder-build
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ set -eo pipefail
[[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_AVAILABLE_PATH/config/functions"

fn-builder-herokuish-ensure-cache() {
declare APP="$1"

existing_cache="$("$DOCKER_BIN" volume ls --quiet --filter label=com.dokku.app-name=test --filter label=com.dokku.builder-type=herokuish)"
if [[ "$existing_cache" != "cache-$APP" ]]; then
"$DOCKER_BIN" volume rm "cache-$APP" >/dev/null 2>&1 || true
"$DOCKER_BIN" volume create "--label=org.label-schema.schema-version=1.0" "--label=org.label-schema.vendor=dokku" "--label=com.dokku.app-name=$APP" "--label=com.dokku.builder-type=herokuish" "cache-$APP" >/dev/null
fi
}

trigger-builder-herokuish-builder-build() {
declare desc="builder-herokuish builder-build plugin trigger"
declare trigger="builder-build"
Expand All @@ -21,8 +31,6 @@ trigger-builder-herokuish-builder-build() {
fi

local IMAGE=$(get_app_image_name "$APP")
local DOKKU_APP_CACHE_DIR="$DOKKU_ROOT/$APP/cache"
local DOKKU_APP_HOST_CACHE_DIR="$DOKKU_HOST_ROOT/$APP/cache"
local DOCKER_COMMIT_LABEL_ARGS=("--change" "LABEL dokku=" "--change" "LABEL org.label-schema.schema-version=1.0" "--change" "LABEL org.label-schema.vendor=dokku" "--change" "LABEL com.dokku.image-stage=build" "--change" "LABEL com.dokku.builder-type=herokuish" "--change" "LABEL com.dokku.app-name=$APP")
local DOCKER_RUN_LABEL_ARGS=("--label=dokku" "--label=org.label-schema.schema-version=1.0" "--label=org.label-schema.vendor=dokku" "--label=com.dokku.image-stage=build" "--label=com.dokku.builder-type=herokuish" "--label=com.dokku.app-name=$APP")
local CID TAR_CID
Expand All @@ -49,7 +57,6 @@ trigger-builder-herokuish-builder-build() {
"$DOCKER_BIN" container commit "${DOCKER_COMMIT_LABEL_ARGS[@]}" "$TAR_CID" "$IMAGE" >/dev/null
DOKKU_SKIP_IMAGE_CLEANUP_REGISTRATION=1 plugn trigger scheduler-register-retired "$APP" "$TAR_CID"

[[ -d $DOKKU_APP_CACHE_DIR ]] || mkdir -p "$DOKKU_APP_CACHE_DIR"
plugn trigger pre-build-buildpack "$APP" "$SOURCECODE_WORK_DIR"

local DOCKER_ARGS=$(: | plugn trigger docker-args-build "$APP" "$BUILDER_TYPE")
Expand All @@ -60,8 +67,8 @@ trigger-builder-herokuish-builder-build() {
eval "ARG_ARRAY=($DOCKER_ARGS)"

local DOKKU_CONTAINER_EXIT_CODE=0
if ! CID=$("$DOCKER_BIN" container create "${DOCKER_RUN_LABEL_ARGS[@]}" $DOKKU_GLOBAL_RUN_ARGS -v "$DOKKU_APP_HOST_CACHE_DIR:/cache" --env=CACHE_PATH=/cache "${ARG_ARRAY[@]}" "$IMAGE" /build); then
DOKKU_SKIP_IMAGE_CLEANUP_REGISTRATION=1 plugn trigger scheduler-register-retired "$APP" "$TAR_CID"
fn-builder-herokuish-ensure-cache "$APP"
if ! CID=$("$DOCKER_BIN" container create "${DOCKER_RUN_LABEL_ARGS[@]}" $DOKKU_GLOBAL_RUN_ARGS -v "cache-$APP:/cache" --env=CACHE_PATH=/cache "${ARG_ARRAY[@]}" "$IMAGE" /build); then
plugn trigger scheduler-register-retired "$APP" "$CID"
dokku_log_warn "Failure during app build"
return 1
Expand All @@ -70,22 +77,19 @@ trigger-builder-herokuish-builder-build() {
plugn trigger post-container-create "app" "$CID" "$APP" "build"
"$DOCKER_BIN" container start "$CID" >/dev/null || DOKKU_CONTAINER_EXIT_CODE=$?
if ! "$DOCKER_BIN" container attach "$CID"; then
DOKKU_SKIP_IMAGE_CLEANUP_REGISTRATION=1 plugn trigger scheduler-register-retired "$APP" "$TAR_CID"
plugn trigger scheduler-register-retired "$APP" "$CID"
dokku_log_warn "Failure during app build"
return 1
fi

DOKKU_CONTAINER_EXIT_CODE="$("$DOCKER_BIN" container wait "$CID" 2>/dev/null || echo "$DOKKU_CONTAINER_EXIT_CODE")"
if [[ "$DOKKU_CONTAINER_EXIT_CODE" -ne 0 ]]; then
DOKKU_SKIP_IMAGE_CLEANUP_REGISTRATION=1 plugn trigger scheduler-register-retired "$APP" "$TAR_CID"
plugn trigger scheduler-register-retired "$APP" "$CID"
dokku_log_warn "Failure during app build"
return 1
fi

"$DOCKER_BIN" container commit "${DOCKER_COMMIT_LABEL_ARGS[@]}" "$CID" "$IMAGE" >/dev/null
DOKKU_SKIP_IMAGE_CLEANUP_REGISTRATION=1 plugn trigger scheduler-register-retired "$APP" "$TAR_CID"
plugn trigger scheduler-register-retired "$APP" "$CID"
plugn trigger post-build-buildpack "$APP" "$SOURCECODE_WORK_DIR"
}
Expand Down
15 changes: 15 additions & 0 deletions plugins/builder-herokuish/install
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
#!/usr/bin/env bash
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions"
set -eo pipefail
[[ $DOKKU_TRACE ]] && set -x

fn-builder-herokuish-remove-old-cache() {
for app in $(dokku_apps "false" 2>/dev/null); do
local DOKKU_APP_CACHE_DIR="$DOKKU_ROOT/$APP/cache"
local DOKKU_APP_HOST_CACHE_DIR="$DOKKU_HOST_ROOT/$APP/cache"
if [[ ! -d "$DOKKU_APP_CACHE_DIR" ]]; then
continue
fi

"$DOCKER_BIN" container run --rm --label=dokku --label=org.label-schema.schema-version=1.0 --label=org.label-schema.vendor=dokku "--label=com.dokku.app-name=$APP" -v "$DOKKU_APP_HOST_CACHE_DIR:/cache" "$DOKKU_IMAGE" "find /cache -depth -mindepth 1 -maxdepth 1 -exec rm -Rf {} ;"
rm -rf "$DOKKU_APP_CACHE_DIR"
done
}

trigger-builder-herokuish-install() {
declare desc="installs the builder-herokuish plugin"
declare trigger="install"

fn-plugin-property-setup "builder-herokuish"
fn-builder-herokuish-remove-old-cache
}

trigger-builder-herokuish-install "$@"
28 changes: 19 additions & 9 deletions plugins/common/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ func DockerCleanup(appName string, forceCleanup bool) error {
containerIDs := append(exitedContainerIDs, deadContainerIDs...)

if len(containerIDs) > 0 {
removeContainers(containerIDs)
DockerRemoveContainers(containerIDs)
}

// delete dangling images
Expand Down Expand Up @@ -351,21 +351,18 @@ func VerifyImage(image string) bool {
return imageCmd.Execute()
}

func listContainers(status string, appName string) ([]string, error) {
// DockerFilterContainers returns a slice of container IDs based on the passed in filters
func DockerFilterContainers(filters []string) ([]string, error) {
command := []string{
DockerBin(),
"container",
"list",
"--quiet",
"--all",
"--filter",
fmt.Sprintf("status=%v", status),
"--filter",
fmt.Sprintf("label=%v", os.Getenv("DOKKU_CONTAINER_LABEL")),
}

if appName != "" {
command = append(command, []string{"--filter", fmt.Sprintf("label=com.dokku.app-name=%v", appName)}...)
for _, filter := range filters {
command = append(command, "--filter", filter)
}

var stderr bytes.Buffer
Expand All @@ -382,6 +379,18 @@ func listContainers(status string, appName string) ([]string, error) {
return output, nil
}

func listContainers(status string, appName string) ([]string, error) {
filters := []string{
fmt.Sprintf("status=%v", status),
fmt.Sprintf("label=%v", os.Getenv("DOKKU_CONTAINER_LABEL")),
}

if appName != "" {
filters = append(filters, fmt.Sprintf("label=com.dokku.app-name=%v", appName))
}
return DockerFilterContainers(filters)
}

func pruneUnusedImages(appName string) {
command := []string{
DockerBin(),
Expand All @@ -400,7 +409,8 @@ func pruneUnusedImages(appName string) {
pruneCmd.Execute()
}

func removeContainers(containerIDs []string) {
// DockerRemoveContainers will call `docker container rm` on the specified containers
func DockerRemoveContainers(containerIDs []string) {
command := []string{
DockerBin(),
"container",
Expand Down
5 changes: 5 additions & 0 deletions plugins/common/subprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type ShellCmd struct {
CommandString string
Args []string
ShowOutput bool
ExitError *exec.ExitError
}

// NewShellCmd returns a new ShellCmd struct
Expand Down Expand Up @@ -57,6 +58,10 @@ func (sc *ShellCmd) Execute() bool {
sc.setup()

if err := sc.Command.Run(); err != nil {
exitError, ok := err.(*exec.ExitError)
if ok {
sc.ExitError = exitError
}
return false
}
return true
Expand Down
3 changes: 1 addition & 2 deletions plugins/repo/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@
/subcommands/*
/triggers/*
/triggers
/pre-delete
/post-stack-set
/post-*
2 changes: 1 addition & 1 deletion plugins/repo/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
SUBCOMMANDS = subcommands/gc subcommands/purge-cache
TRIGGERS = triggers/post-stack-set triggers/pre-delete
TRIGGERS = triggers/post-stack-set triggers/post-delete
BUILD = commands subcommands triggers
PLUGIN_NAME = repo

Expand Down
51 changes: 34 additions & 17 deletions plugins/repo/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,45 @@ import (
"strings"

"github.com/dokku/dokku/plugins/common"
"github.com/dokku/dokku/plugins/config"
)

// PurgeCacheFailed wraps error to allow returning the correct exit code
type PurgeCacheFailed struct {
exitCode int
}

// ExitCode returns an exit code to use in case this error bubbles
// up into an os.Exit() call
func (err *PurgeCacheFailed) ExitCode() int {
return err.exitCode
}

// Error returns a standard non-existent app error
func (err *PurgeCacheFailed) Error() string {
return fmt.Sprintf("failed to purge cache, exit code %d", err.exitCode)
}

// PurgeCache deletes the contents of the build cache stored in the repository
func PurgeCache(appName string) error {
cacheDir := strings.Join([]string{common.AppRoot(appName), "cache"}, "/")
cacheHostDir := strings.Join([]string{common.AppHostRoot(appName), "cache"}, "/")
dokkuGlobalRunArgs := common.MustGetEnv("DOKKU_GLOBAL_RUN_ARGS")
image := config.GetWithDefault(appName, "DOKKU_IMAGE", os.Getenv("DOKKU_IMAGE"))
if info, _ := os.Stat(cacheDir); info != nil && info.IsDir() {
dockerLabelArgs := fmt.Sprintf("--label=com.dokku.app-name=%s", appName)
purgeCacheCmd := common.NewShellCmd(strings.Join([]string{
common.DockerBin(),
"container",
"run", "--rm", dockerLabelArgs, dokkuGlobalRunArgs,
"-v", strings.Join([]string{cacheHostDir, ":/cache"}, ""), image,
`find /cache -depth -mindepth 1 -maxdepth 1 -exec rm -Rf {} ;`}, " "))
purgeCacheCmd.Execute()
err := os.MkdirAll(cacheDir, 0644)
if err != nil {
return err
containerIDs, _ := common.DockerFilterContainers([]string{
fmt.Sprintf("label=com.dokku.app-name=%v", appName),
"label=com.dokku.image-stage=build",
})
if len(containerIDs) > 0 {
common.DockerRemoveContainers(containerIDs)
}
purgeCacheCmd := common.NewShellCmd(strings.Join([]string{
common.DockerBin(),
"volume",
"rm", "-f", fmt.Sprintf("cache-%s", appName)}, " "))
purgeCacheCmd.ShowOutput = false
purgeCacheCmd.Command.Stderr = os.Stderr
if !purgeCacheCmd.Execute() {
exitCode := 1
if purgeCacheCmd.ExitError != nil {
exitCode = purgeCacheCmd.ExitError.ExitCode()
}
return &PurgeCacheFailed{exitCode}
}

return nil
Expand Down
2 changes: 1 addition & 1 deletion plugins/repo/src/triggers/triggers.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func main() {
case "post-stack-set":
appName := flag.Arg(0)
err = repo.PurgeCache(appName)
case "pre-delete":
case "post-delete":
appName := flag.Arg(0)
err = repo.PurgeCache(appName)
default:
Expand Down
8 changes: 6 additions & 2 deletions tests/unit/build-env.bats
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,16 @@ teardown() {
}

@test "(build-env) buildpack deploy with Dockerfile" {
run /bin/bash -c "dokku config:set --no-restart $TEST_APP BUILDPACK_URL='https://github.com/heroku/heroku-buildpack-nodejs'"
run /bin/bash -c "dokku config:set --no-restart $TEST_APP BUILDPACK_URL='https://github.com/dokku/heroku-buildpack-null'"
echo "output: $output"
echo "status: $status"
assert_success

run deploy_app python dokku@dokku.me:$TEST_APP move_dockerfile_into_place
echo "output: $output"
echo "status: $status"
assert_success

deploy_app dockerfile
run /bin/bash -c "dokku --quiet config:get $TEST_APP DOKKU_APP_TYPE"
echo "output: $output"
echo "status: $status"
Expand Down
23 changes: 16 additions & 7 deletions tests/unit/repo.bats
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ load test_helper

setup() {
global_setup
create_app
}

teardown() {
destroy_app
global_teardown
}

Expand All @@ -24,7 +26,7 @@ teardown() {
assert_output "$help_output"
}

@test "(repo) repo:gc, repo:purge-cache" {
@test "(repo) repo:gc" {
run deploy_app
echo "output: $output"
echo "status: $status"
Expand All @@ -34,29 +36,36 @@ teardown() {
echo "output: $output"
echo "status: $status"
assert_success
}

run /bin/bash -c "touch $DOKKU_ROOT/$TEST_APP/cache/derp"
@test "(repo) repo:purge-cache" {
run deploy_app
echo "output: $output"
echo "status: $status"
assert_success

run /bin/bash -c "docker volume ls -q --filter label=com.dokku.app-name=$TEST_APP | wc -l"
echo "count: '$output'"
echo "status: $status"
assert_output 1

run /bin/bash -c "find $DOKKU_ROOT/$TEST_APP/cache -type f | wc -l"
echo "count: '$output'"
echo "status: $status"
assert_not_output 0
assert_output 0

run /bin/bash -c "dokku repo:purge-cache $TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success

run /bin/bash -c "find $DOKKU_ROOT/$TEST_APP/cache -type f | wc -l"
run /bin/bash -c "docker volume ls -q --filter label=com.dokku.app-name=$TEST_APP | wc -l"
echo "count: '$output'"
echo "status: $status"
assert_output 0

run destroy_app
echo "output: $output"
run /bin/bash -c "find $DOKKU_ROOT/$TEST_APP/cache -type f | wc -l"
echo "count: '$output'"
echo "status: $status"
assert_success
assert_output 0
}
7 changes: 7 additions & 0 deletions tests/unit/test_helper.bash
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,13 @@ add_postdeploy_command() {
echo "${contents}" >"$APP_REPO_DIR/app.json"
}

move_dockerfile_into_place() {
local APP="$1"
local APP_REPO_DIR="$2"
[[ -z "$APP" ]] && local APP="$TEST_APP"
mv "$APP_REPO_DIR/alt.Dockerfile" "$APP_REPO_DIR/Dockerfile"
}

add_requirements_txt() {
local APP="$1"
local APP_REPO_DIR="$2"
Expand Down