mirror of
https://github.com/dokku/dokku.git
synced 2025-12-29 00:25:08 +01:00
Merge pull request #4395 from dokku/cnb-env-vars
Add environment variable support to CNB-based containers
This commit is contained in:
@@ -47,14 +47,14 @@ trigger-builder-herokuish-builder-build() {
|
||||
plugn trigger pre-build-buildpack "$APP" "$SOURCECODE_WORK_DIR"
|
||||
|
||||
local DOCKER_ARGS=$(: | plugn trigger docker-args-build "$APP" "$BUILDER_TYPE")
|
||||
[[ "$DOKKU_TRACE" ]] && DOCKER_ARGS+=" -e TRACE=true "
|
||||
[[ "$DOKKU_TRACE" ]] && DOCKER_ARGS+=" --env=TRACE=true "
|
||||
DOCKER_ARGS+=$(: | plugn trigger docker-args-process-build "$APP" "$BUILDER_TYPE")
|
||||
|
||||
declare -a ARG_ARRAY
|
||||
eval "ARG_ARRAY=($DOCKER_ARGS)"
|
||||
|
||||
local DOKKU_CONTAINER_EXIT_CODE=0
|
||||
local CID=$("$DOCKER_BIN" container create "${DOCKER_RUN_LABEL_ARGS[@]}" $DOKKU_GLOBAL_RUN_ARGS -v $DOKKU_APP_HOST_CACHE_DIR:/cache -e CACHE_PATH=/cache "${ARG_ARRAY[@]}" $IMAGE /build)
|
||||
local 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)
|
||||
plugn trigger post-container-create "app" "$CID" "$APP" "build"
|
||||
"$DOCKER_BIN" container start "$CID" >/dev/null || DOKKU_CONTAINER_EXIT_CODE=$?
|
||||
"$DOCKER_BIN" container attach "$CID"
|
||||
|
||||
@@ -14,6 +14,12 @@ trigger-config-docker-args() {
|
||||
STDIN=$(cat)
|
||||
trigger="$0 config_docker_args"
|
||||
|
||||
if is_image_cnb_based "$IMAGE"; then
|
||||
ENV_ARGS="$(config_export app "$APP" --format docker-args-keys --merged)"
|
||||
echo -n "$STDIN $ENV_ARGS"
|
||||
return
|
||||
fi
|
||||
|
||||
if ! is_image_herokuish_based "$IMAGE" "$APP"; then
|
||||
ENV_ARGS="$(config_export app "$APP" --format docker-args --merged)"
|
||||
echo -n "$STDIN $ENV_ARGS"
|
||||
|
||||
@@ -24,8 +24,10 @@ const (
|
||||
ExportFormatExports ExportFormat = iota
|
||||
//ExportFormatEnvfile format: dotenv file
|
||||
ExportFormatEnvfile
|
||||
//ExportFormatDockerArgs format: --env args for docker
|
||||
//ExportFormatDockerArgs format: --env KEY=VALUE args for docker
|
||||
ExportFormatDockerArgs
|
||||
//ExportFormatDockerArgsKeys format: --env KEY args for docker
|
||||
ExportFormatDockerArgsKeys
|
||||
//ExportFormatShell format: env arguments for shell
|
||||
ExportFormatShell
|
||||
//ExportFormatPretty format: pretty-printed in columns
|
||||
@@ -171,6 +173,8 @@ func (e *Env) Export(format ExportFormat) string {
|
||||
return e.EnvfileString()
|
||||
case ExportFormatDockerArgs:
|
||||
return e.DockerArgsString()
|
||||
case ExportFormatDockerArgsKeys:
|
||||
return e.DockerArgsKeysString()
|
||||
case ExportFormatShell:
|
||||
return e.ShellString()
|
||||
case ExportFormatPretty:
|
||||
@@ -201,6 +205,16 @@ func (e *Env) DockerArgsString() string {
|
||||
return e.stringWithPrefixAndSeparator("--env=", " ")
|
||||
}
|
||||
|
||||
//DockerArgsKeysString gets the contents of this Env in the form -env=KEY --env...
|
||||
func (e *Env) DockerArgsKeysString() string {
|
||||
keys := e.Keys()
|
||||
entries := make([]string, len(keys))
|
||||
for i, k := range keys {
|
||||
entries[i] = fmt.Sprintf("%s%s", "--env=", k)
|
||||
}
|
||||
return strings.Join(entries, " ")
|
||||
}
|
||||
|
||||
//JSONString returns the contents of this Env as a key/value json object
|
||||
func (e *Env) JSONString() string {
|
||||
data, err := json.Marshal(e.Map())
|
||||
|
||||
@@ -54,6 +54,7 @@ func TestExport(t *testing.T) {
|
||||
e, _ := newEnvFromString("BAR='BAZ'\nFOO='b'ar '\nBAZ='a\\nb'")
|
||||
Expect(e.Export(ExportFormatEnvfile)).To(Equal("BAR=\"BAZ\"\nBAZ=\"a\\nb\"\nFOO=\"b'ar \""))
|
||||
Expect(e.Export(ExportFormatDockerArgs)).To(Equal("--env=BAR='BAZ' --env=BAZ='a\nb' --env=FOO='b'\\''ar '"))
|
||||
Expect(e.Export(ExportFormatDockerArgsKeys)).To(Equal("--env=BAR --env=BAZ --env=FOO"))
|
||||
Expect(e.Export(ExportFormatShell)).To(Equal("BAR='BAZ' BAZ='a\nb' FOO='b'\\''ar '"))
|
||||
Expect(e.Export(ExportFormatExports)).To(Equal("export BAR='BAZ'\nexport BAZ='a\nb'\nexport FOO='b'\\''ar '"))
|
||||
Expect(e.Export(ExportFormatPretty)).To(Equal("BAR: BAZ\nBAZ: a\nb\nFOO: b'ar"))
|
||||
|
||||
@@ -49,7 +49,7 @@ func main() {
|
||||
args := flag.NewFlagSet("config:export", flag.ExitOnError)
|
||||
global := args.Bool("global", false, "--global: use the global environment")
|
||||
merged := args.Bool("merged", false, "--merged: merge app environment and global environment")
|
||||
format := args.String("format", "exports", "--format: [ exports | envfile | docker-args | shell | pretty | json | json-list ] which format to export as)")
|
||||
format := args.String("format", "exports", "--format: [ exports | envfile | docker-args | docker-args-keys | shell | pretty | json | json-list ] which format to export as)")
|
||||
args.Parse(os.Args[2:])
|
||||
if !*global {
|
||||
appName = args.Arg(0)
|
||||
|
||||
@@ -43,13 +43,14 @@ func CommandExport(appName string, global bool, merged bool, format string) erro
|
||||
suffix := "\n"
|
||||
|
||||
exportTypes := map[string]ExportFormat{
|
||||
"exports": ExportFormatExports,
|
||||
"envfile": ExportFormatEnvfile,
|
||||
"docker-args": ExportFormatDockerArgs,
|
||||
"shell": ExportFormatShell,
|
||||
"pretty": ExportFormatPretty,
|
||||
"json": ExportFormatJSON,
|
||||
"json-list": ExportFormatJSONList,
|
||||
"exports": ExportFormatExports,
|
||||
"envfile": ExportFormatEnvfile,
|
||||
"docker-args": ExportFormatDockerArgs,
|
||||
"docker-args-keys": ExportFormatDockerArgsKeys,
|
||||
"shell": ExportFormatShell,
|
||||
"pretty": ExportFormatPretty,
|
||||
"json": ExportFormatJSON,
|
||||
"json-list": ExportFormatJSONList,
|
||||
}
|
||||
|
||||
exportType, ok := exportTypes[format]
|
||||
|
||||
@@ -49,7 +49,7 @@ func TriggerDockerArgsProcessDeploy(appName string) error {
|
||||
}
|
||||
|
||||
if maxSize != "unlimited" {
|
||||
fmt.Printf(" --log-opt max-size=%s ", maxSize)
|
||||
fmt.Printf(" --log-opt=max-size=%s ", maxSize)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ trigger-scheduler-docker-local-scheduler-deploy() {
|
||||
|
||||
rm -f "${DOKKU_LIB_ROOT}/data/scheduler-docker-local/$APP/failed-containers"
|
||||
|
||||
local DOCKER_RUN_LABEL_ARGS="--label=com.dokku.app-name=$APP"
|
||||
local DOCKER_RUN_LABEL_ARGS="--label=com.dokku.app-name=$APP --label=com.dokku.container-type=deploy"
|
||||
local DOKKU_DOCKER_STOP_TIMEOUT DOKKU_HEROKUISH DOKKU_NETWORK_BIND_ALL IMAGE
|
||||
DOKKU_HEROKUISH=false
|
||||
IMAGE=$(get_deploying_app_image_name "$APP" "$IMAGE_TAG")
|
||||
@@ -72,43 +72,40 @@ trigger-scheduler-docker-local-scheduler-deploy() {
|
||||
# start the app
|
||||
local DOCKER_ARGS
|
||||
DOCKER_ARGS=$(: | plugn trigger docker-args-deploy "$APP" "$IMAGE_TAG" "$PROC_TYPE" "$CONTAINER_INDEX")
|
||||
DOCKER_ARGS+=" -e DYNO=$DYNO "
|
||||
DOCKER_ARGS+=" --label=com.dokku.process-type=$PROC_TYPE --label=com.dokku.dyno=$DYNO "
|
||||
DOCKER_ARGS+=" --env=DYNO=$DYNO "
|
||||
DOCKER_ARGS+=" --init "
|
||||
DOCKER_ARGS+=" $DOCKER_RUN_LABEL_ARGS $DOKKU_GLOBAL_RUN_ARGS "
|
||||
DOCKER_ARGS+=$(: | plugn trigger docker-args-process-deploy "$APP" "$IMAGE_SOURCE_TYPE" "$IMAGE_TAG" "$PROC_TYPE" "$CONTAINER_INDEX")
|
||||
[[ "$DOKKU_TRACE" ]] && DOCKER_ARGS+=" -e TRACE=true "
|
||||
|
||||
declare -a ARG_ARRAY
|
||||
eval "ARG_ARRAY=($DOCKER_ARGS)"
|
||||
[[ "$DOKKU_TRACE" ]] && DOCKER_ARGS+=" --env=TRACE=true "
|
||||
|
||||
local START_CMD
|
||||
[[ "$DOKKU_HEROKUISH" == "true" ]] && START_CMD="/start $PROC_TYPE"
|
||||
[[ -n "$DOKKU_START_CMD" ]] && START_CMD="$DOKKU_START_CMD"
|
||||
|
||||
local DOKKU_PORT=""
|
||||
if [[ "$PROC_TYPE" == "web" ]]; then
|
||||
ports=($(plugn trigger network-compute-ports "$APP" "$PROC_TYPE" "$DOKKU_HEROKUISH" "$CONTAINER_INDEX"))
|
||||
local DOKKU_DOCKER_PORT_ARGS=""
|
||||
local DOKKU_PORT=""
|
||||
for p in "${ports[@]}"; do
|
||||
if [[ ! "$p" =~ .*udp.* ]]; then
|
||||
DOKKU_PORT=${DOKKU_PORT:="$p"}
|
||||
fi
|
||||
DOKKU_DOCKER_PORT_ARGS+=" -p $p "
|
||||
|
||||
if [[ "$DOKKU_NETWORK_BIND_ALL" == "true" ]]; then
|
||||
DOCKER_ARGS+=" -p $p "
|
||||
fi
|
||||
done
|
||||
|
||||
START_CMD=$(fn-scheduler-docker-local-extract-start-cmd "$APP" "$PROC_TYPE" "$START_CMD" "$DOKKU_HEROKUISH" "$DOKKU_PORT")
|
||||
if [[ "$DOKKU_NETWORK_BIND_ALL" == "false" ]]; then
|
||||
# shellcheck disable=SC2086
|
||||
cid=$("$DOCKER_BIN" container create --label=com.dokku.container-type=deploy --label=com.dokku.process-type=$PROC_TYPE --label=com.dokku.dyno=$DYNO "${DOCKER_RUN_LABEL_ARGS[@]}" $DOKKU_GLOBAL_RUN_ARGS --init --env PORT=$DOKKU_PORT "${ARG_ARRAY[@]}" $IMAGE $START_CMD)
|
||||
else
|
||||
# shellcheck disable=SC2086
|
||||
cid=$("$DOCKER_BIN" container create --label=com.dokku.container-type=deploy --label=com.dokku.process-type=$PROC_TYPE --label=com.dokku.dyno=$DYNO "${DOCKER_RUN_LABEL_ARGS[@]}" $DOKKU_GLOBAL_RUN_ARGS --init $DOKKU_DOCKER_PORT_ARGS --env PORT=$DOKKU_PORT "${ARG_ARRAY[@]}" $IMAGE $START_CMD)
|
||||
fi
|
||||
else
|
||||
START_CMD=$(fn-scheduler-docker-local-extract-start-cmd "$APP" "$PROC_TYPE" "$START_CMD" "$DOKKU_HEROKUISH")
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
cid=$("$DOCKER_BIN" container create --label=com.dokku.container-type=deploy --label=com.dokku.process-type=$PROC_TYPE --label=com.dokku.dyno=$DYNO "${DOCKER_RUN_LABEL_ARGS[@]}" $DOKKU_GLOBAL_RUN_ARGS --init --env PORT=$DOKKU_PORT "${ARG_ARRAY[@]}" $IMAGE $START_CMD)
|
||||
fi
|
||||
|
||||
DOCKER_ARGS+=" --env=PORT=$DOKKU_PORT "
|
||||
|
||||
START_CMD=$(fn-scheduler-docker-local-extract-start-cmd "$APP" "$PROC_TYPE" "$START_CMD" "$DOKKU_HEROKUISH" "$DOKKU_PORT")
|
||||
DOCKER_ARGS+=" $IMAGE "
|
||||
DOCKER_ARGS+=" $START_CMD "
|
||||
|
||||
cid=$(fn-start-app-container "$DOCKER_ARGS")
|
||||
|
||||
plugn trigger post-container-create "app" "$cid" "$APP" "deploy" "$PROC_TYPE"
|
||||
"$DOCKER_BIN" container start "$cid" >/dev/null || true
|
||||
|
||||
@@ -219,4 +216,14 @@ fn-scheduler-docker-local-extract-start-cmd() {
|
||||
echo "$START_CMD"
|
||||
}
|
||||
|
||||
fn-start-app-container() {
|
||||
declare desc="starts a single app container"
|
||||
declare DOCKER_ARGS="$1"
|
||||
|
||||
declare -a __DOKKU_DOCKER_ARG_ARRAY
|
||||
eval "__DOKKU_DOCKER_ARG_ARRAY=($DOCKER_ARGS)"
|
||||
eval "$(config_export app "$APP")"
|
||||
"$DOCKER_BIN" container create "${__DOKKU_DOCKER_ARG_ARRAY[@]}"
|
||||
}
|
||||
|
||||
trigger-scheduler-docker-local-scheduler-deploy "$@"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import http.server
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
@@ -7,7 +8,12 @@ class GetHandler(http.server.BaseHTTPRequestHandler):
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "text/plain; charset=utf-8")
|
||||
self.end_headers()
|
||||
self.wfile.write("python/http.server".encode("utf-8"))
|
||||
|
||||
if self.path == '/':
|
||||
self.wfile.write("python/http.server".encode("utf-8"))
|
||||
else:
|
||||
data = json.dumps(dict(os.environ), sort_keys=True, indent=4)
|
||||
self.wfile.write(data.encode("utf-8"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -303,9 +303,14 @@ teardown() {
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku docker-options:add $TEST_APP build \"--link postgres\""
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
deploy_app dockerfile
|
||||
|
||||
run deploy_app dockerfile
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
}
|
||||
|
||||
@@ -385,7 +385,7 @@ teardown() {
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "--log-opt max-size=20m"
|
||||
assert_output "--log-opt=max-size=20m"
|
||||
|
||||
run /bin/bash -c "dokku docker-options:add $TEST_APP deploy --log-driver=local" 2>&1
|
||||
echo "output: $output"
|
||||
@@ -396,7 +396,7 @@ teardown() {
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "--log-opt max-size=20m"
|
||||
assert_output "--log-opt=max-size=20m"
|
||||
|
||||
run /bin/bash -c "dokku docker-options:add $TEST_APP deploy --log-driver=json-file" 2>&1
|
||||
echo "output: $output"
|
||||
@@ -407,7 +407,7 @@ teardown() {
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "--log-opt max-size=20m"
|
||||
assert_output "--log-opt=max-size=20m"
|
||||
|
||||
run /bin/bash -c "dokku docker-options:add $TEST_APP deploy --log-driver=journald" 2>&1
|
||||
echo "output: $output"
|
||||
|
||||
37
tests/unit/ps-cnb.bats
Normal file
37
tests/unit/ps-cnb.bats
Normal file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
setup_file() {
|
||||
add-apt-repository --yes ppa:cncf-buildpacks/pack-cli
|
||||
apt-get update
|
||||
apt-get --yes install pack-cli
|
||||
}
|
||||
|
||||
setup() {
|
||||
global_setup
|
||||
create_app
|
||||
}
|
||||
|
||||
teardown() {
|
||||
destroy_app
|
||||
global_teardown
|
||||
}
|
||||
|
||||
@test "(ps) cnb env vars" {
|
||||
run /bin/bash -c "dokku config:set $TEST_APP DOKKU_CNB_EXPERIMENTAL=1"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
run deploy_app python dokku@dokku.me:$TEST_APP add_requirements_txt
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "curl $(dokku url $TEST_APP)/env"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output_contains '"DOKKU_CNB_EXPERIMENTAL": "1"'
|
||||
}
|
||||
@@ -9,7 +9,6 @@ setup() {
|
||||
|
||||
teardown() {
|
||||
destroy_app
|
||||
destroy_app 0 "$MYAPP" || true
|
||||
global_teardown
|
||||
}
|
||||
|
||||
|
||||
@@ -513,6 +513,13 @@ add_release_command() {
|
||||
echo "release: touch /app/release.test" >> "$APP_REPO_DIR/Procfile"
|
||||
}
|
||||
|
||||
add_requirements_txt() {
|
||||
local APP="$1"
|
||||
local APP_REPO_DIR="$2"
|
||||
[[ -z "$APP" ]] && local APP="$TEST_APP"
|
||||
echo "flask" >> "$APP_REPO_DIR/requirements.txt"
|
||||
}
|
||||
|
||||
build_nginx_config() {
|
||||
# simulate nginx post-deploy
|
||||
dokku domains:setup "$TEST_APP"
|
||||
|
||||
Reference in New Issue
Block a user