feat: port vhost proxy :report subcommands to golang
The bash :report implementations for the caddy, haproxy, openresty, and traefik proxy plugins are replaced with a compiled golang binary that collects report keys in parallel and marshals json directly. The traefik dns-provider values keep their masking behaviour, remaining hidden in the default stdout report while surfacing for --format json or an explicit flag query. These four plugins previously had no unit tests, so a bats suite covering the report matrix is added for each.
This commit is contained in:
4
go.work
4
go.work
@@ -11,13 +11,16 @@ use (
|
||||
./plugins/builder-pack
|
||||
./plugins/builder-railpack
|
||||
./plugins/buildpacks
|
||||
./plugins/caddy-vhosts
|
||||
./plugins/common
|
||||
./plugins/config
|
||||
./plugins/cron
|
||||
./plugins/docker-options
|
||||
./plugins/haproxy-vhosts
|
||||
./plugins/logs
|
||||
./plugins/network
|
||||
./plugins/nginx-vhosts
|
||||
./plugins/openresty-vhosts
|
||||
./plugins/ports
|
||||
./plugins/proxy
|
||||
./plugins/ps
|
||||
@@ -28,4 +31,5 @@ use (
|
||||
./plugins/scheduler-docker-local
|
||||
./plugins/scheduler-k3s
|
||||
./plugins/storage
|
||||
./plugins/traefik-vhosts
|
||||
)
|
||||
|
||||
4
plugins/caddy-vhosts/.gitignore
vendored
Normal file
4
plugins/caddy-vhosts/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/report
|
||||
/report-subcommand
|
||||
/triggers
|
||||
/subcommands/report
|
||||
13
plugins/caddy-vhosts/Makefile
Normal file
13
plugins/caddy-vhosts/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
GOARCH ?= amd64
|
||||
TRIGGERS = triggers/report
|
||||
BUILD = report-subcommand triggers
|
||||
PLUGIN_NAME = caddy-vhosts
|
||||
|
||||
clean-report-subcommand:
|
||||
rm -rf report-subcommand
|
||||
|
||||
report-subcommand: clean-report-subcommand src/subcommands/subcommands.go
|
||||
GOARCH=$(GOARCH) go build -mod=readonly -ldflags="-s -w" $(GO_ARGS) -o report-subcommand src/subcommands/subcommands.go
|
||||
ln -sf ../report-subcommand subcommands/report
|
||||
|
||||
include ../../common.mk
|
||||
107
plugins/caddy-vhosts/command-functions
Executable file → Normal file
107
plugins/caddy-vhosts/command-functions
Executable file → Normal file
@@ -30,113 +30,6 @@ cmd-caddy-labels-show() {
|
||||
cmd-proxy-labels-show "proxy:labels:show" "caddy" "$@"
|
||||
}
|
||||
|
||||
cmd-caddy-report() {
|
||||
declare desc="displays a caddy report for one or more apps"
|
||||
declare cmd="caddy:report"
|
||||
[[ "$1" == "$cmd" ]] && shift 1
|
||||
fn-report-parse-args "$@"
|
||||
set -- "${REPORT_ARGS[@]}"
|
||||
declare APP="${1:-}" INFO_FLAG="${2:-}"
|
||||
|
||||
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
|
||||
INFO_FLAG="$APP"
|
||||
APP=""
|
||||
fi
|
||||
|
||||
if [[ "$REPORT_IS_GLOBAL" == "true" ]]; then
|
||||
APP="--global"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]] && [[ -z "$INFO_FLAG" ]]; then
|
||||
INFO_FLAG="true"
|
||||
fi
|
||||
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
cmd-caddy-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
elif [[ -z "$APP" ]]; then
|
||||
for app in $(dokku_apps); do
|
||||
cmd-caddy-report-single "$app" "$INFO_FLAG" "$REPORT_FORMAT" | tee || true
|
||||
done
|
||||
else
|
||||
cmd-caddy-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd-caddy-report-single() {
|
||||
declare APP="$1" INFO_FLAG="$2" FORMAT="${3:-stdout}"
|
||||
if [[ "$INFO_FLAG" == "true" ]]; then
|
||||
INFO_FLAG=""
|
||||
fi
|
||||
local flag_map=()
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
flag_map=(
|
||||
"--caddy-computed-image: $(fn-caddy-computed-image)"
|
||||
"--caddy-computed-letsencrypt-email: $(fn-caddy-computed-letsencrypt-email)"
|
||||
"--caddy-computed-letsencrypt-server: $(fn-caddy-computed-letsencrypt-server)"
|
||||
"--caddy-computed-log-level: $(fn-caddy-computed-log-level)"
|
||||
"--caddy-computed-polling-interval: $(fn-caddy-computed-polling-interval)"
|
||||
"--caddy-computed-tls-internal: $(fn-caddy-computed-tls-internal "$APP")"
|
||||
"--caddy-global-image: $(fn-caddy-global-image)"
|
||||
"--caddy-global-letsencrypt-email: $(fn-caddy-global-letsencrypt-email)"
|
||||
"--caddy-global-letsencrypt-server: $(fn-caddy-global-letsencrypt-server)"
|
||||
"--caddy-global-log-level: $(fn-caddy-global-log-level)"
|
||||
"--caddy-global-polling-interval: $(fn-caddy-global-polling-interval)"
|
||||
"--caddy-global-tls-internal: $(fn-caddy-global-tls-internal)"
|
||||
)
|
||||
else
|
||||
verify_app_name "$APP"
|
||||
flag_map=(
|
||||
"--caddy-computed-image: $(fn-caddy-computed-image)"
|
||||
"--caddy-computed-letsencrypt-email: $(fn-caddy-computed-letsencrypt-email)"
|
||||
"--caddy-computed-letsencrypt-server: $(fn-caddy-computed-letsencrypt-server)"
|
||||
"--caddy-computed-log-level: $(fn-caddy-computed-log-level)"
|
||||
"--caddy-computed-polling-interval: $(fn-caddy-computed-polling-interval)"
|
||||
"--caddy-computed-tls-internal: $(fn-caddy-computed-tls-internal "$APP")"
|
||||
"--caddy-global-image: $(fn-caddy-global-image)"
|
||||
"--caddy-global-letsencrypt-email: $(fn-caddy-global-letsencrypt-email)"
|
||||
"--caddy-global-letsencrypt-server: $(fn-caddy-global-letsencrypt-server)"
|
||||
"--caddy-global-log-level: $(fn-caddy-global-log-level)"
|
||||
"--caddy-global-polling-interval: $(fn-caddy-global-polling-interval)"
|
||||
"--caddy-global-tls-internal: $(fn-caddy-global-tls-internal)"
|
||||
"--caddy-tls-internal: $(fn-caddy-tls-internal "$APP")"
|
||||
)
|
||||
fi
|
||||
|
||||
fn-report-validate-format "$FORMAT" "$INFO_FLAG"
|
||||
|
||||
if [[ "$FORMAT" == "json" ]]; then
|
||||
fn-report-emit-json flag_map "caddy"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "$INFO_FLAG" ]]; then
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
dokku_log_info2_quiet "global caddy information"
|
||||
else
|
||||
dokku_log_info2_quiet "${APP} caddy information"
|
||||
fi
|
||||
for flag in "${flag_map[@]}"; do
|
||||
key="$(echo "${flag#--}" | cut -f1 -d' ' | tr - ' ')"
|
||||
dokku_log_verbose "$(printf "%-30s %-25s" "${key^}" "${flag#*: }")"
|
||||
done
|
||||
else
|
||||
local match=false
|
||||
for flag in "${flag_map[@]}"; do
|
||||
valid_flags="${valid_flags} $(echo "$flag" | cut -d':' -f1)"
|
||||
if [[ "$flag" == "${INFO_FLAG}:"* ]]; then
|
||||
value=${flag#*: }
|
||||
size="${#value}"
|
||||
if [[ "$size" -ne 0 ]]; then
|
||||
echo "$value" && match=true
|
||||
else
|
||||
match=true
|
||||
fi
|
||||
fi
|
||||
done
|
||||
[[ "$match" == "true" ]] || dokku_log_fail "Invalid flag passed, valid flags:${valid_flags}"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd-caddy-logs() {
|
||||
declare desc="display caddy logs from command line"
|
||||
declare cmd="caddy:logs"
|
||||
|
||||
29
plugins/caddy-vhosts/go.mod
Normal file
29
plugins/caddy-vhosts/go.mod
Normal file
@@ -0,0 +1,29 @@
|
||||
module github.com/dokku/dokku/plugins/caddy-vhosts
|
||||
|
||||
go 1.26.2
|
||||
|
||||
require (
|
||||
github.com/dokku/dokku/plugins/common v0.0.0-00010101000000-000000000000
|
||||
github.com/spf13/pflag v1.0.10
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/fatih/color v1.19.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/melbahja/goph v1.5.1 // indirect
|
||||
github.com/otiai10/copy v1.14.1 // indirect
|
||||
github.com/otiai10/mint v1.6.3 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/sftp v1.13.10 // indirect
|
||||
github.com/ryanuber/columnize v2.1.2+incompatible // indirect
|
||||
golang.org/x/crypto v0.53.0 // indirect
|
||||
golang.org/x/sync v0.21.0 // indirect
|
||||
golang.org/x/sys v0.46.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/dokku/dokku/plugins/common => ../common
|
||||
55
plugins/caddy-vhosts/go.sum
Normal file
55
plugins/caddy-vhosts/go.sum
Normal file
@@ -0,0 +1,55 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w=
|
||||
github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/melbahja/goph v1.5.1 h1:gdZyjn5nM6FO6mAZrv7XqE2gArQbb+V6FdIyH3Ru3vA=
|
||||
github.com/melbahja/goph v1.5.1/go.mod h1:dDwo+44cmvfDLdiVpc6fJxexf5BA5yEDUeE5YgtuDO4=
|
||||
github.com/onsi/gomega v1.42.1 h1:iN1rCUX+44NZ1Dc97MPoeFYbFR0vh8zxoxMFwKdyZ6I=
|
||||
github.com/onsi/gomega v1.42.1/go.mod h1:REff/hsDsodHoKlWsP2mAPhu1+5/6hVYNf9rIEBpeSg=
|
||||
github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8=
|
||||
github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I=
|
||||
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=
|
||||
github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.10 h1:+5FbKNTe5Z9aspU88DPIKJ9z2KZoaGCu6Sr6kKR/5mU=
|
||||
github.com/pkg/sftp v1.13.10/go.mod h1:bJ1a7uDhrX/4OII+agvy28lzRvQrmIQuaHrcI1HbeGA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/ryanuber/columnize v2.1.2+incompatible h1:C89EOx/XBWwIXl8wm8OPJBd7kPF25UfsK2X7Ph/zCAk=
|
||||
github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
|
||||
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
|
||||
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
|
||||
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
|
||||
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
|
||||
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
|
||||
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
|
||||
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
|
||||
golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
|
||||
golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$PLUGIN_AVAILABLE_PATH/caddy-vhosts/command-functions"
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
cmd-caddy-report-single "$@"
|
||||
155
plugins/caddy-vhosts/report.go
Normal file
155
plugins/caddy-vhosts/report.go
Normal file
@@ -0,0 +1,155 @@
|
||||
package caddyvhosts
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
// ReportSingleApp is an internal function that displays the caddy report for one or more apps
|
||||
func ReportSingleApp(appName string, format string, infoFlag string) error {
|
||||
if appName != "--global" {
|
||||
if err := common.VerifyAppName(appName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
flags := map[string]common.ReportFunc{
|
||||
"--caddy-computed-image": reportComputedImage,
|
||||
"--caddy-computed-letsencrypt-email": reportComputedLetsencryptEmail,
|
||||
"--caddy-computed-letsencrypt-server": reportComputedLetsencryptServer,
|
||||
"--caddy-computed-log-level": reportComputedLogLevel,
|
||||
"--caddy-computed-polling-interval": reportComputedPollingInterval,
|
||||
"--caddy-computed-tls-internal": reportComputedTLSInternal,
|
||||
"--caddy-global-image": reportGlobalImage,
|
||||
"--caddy-global-letsencrypt-email": reportGlobalLetsencryptEmail,
|
||||
"--caddy-global-letsencrypt-server": reportGlobalLetsencryptServer,
|
||||
"--caddy-global-log-level": reportGlobalLogLevel,
|
||||
"--caddy-global-polling-interval": reportGlobalPollingInterval,
|
||||
"--caddy-global-tls-internal": reportGlobalTLSInternal,
|
||||
}
|
||||
if appName != "--global" {
|
||||
flags["--caddy-tls-internal"] = reportTLSInternal
|
||||
}
|
||||
|
||||
flagKeys := []string{}
|
||||
for flagKey := range flags {
|
||||
flagKeys = append(flagKeys, flagKey)
|
||||
}
|
||||
|
||||
infoFlags := common.CollectReport(appName, infoFlag, flags)
|
||||
return common.ReportSingleApp(common.ReportSingleAppInput{
|
||||
ReportType: "caddy",
|
||||
AppName: appName,
|
||||
InfoFlag: infoFlag,
|
||||
InfoFlags: infoFlags,
|
||||
InfoFlagKeys: flagKeys,
|
||||
Format: format,
|
||||
TrimPrefix: true,
|
||||
UppercaseFirstCharacter: true,
|
||||
EmitLegacyPrefix: false,
|
||||
})
|
||||
}
|
||||
|
||||
func reportGlobalImage(appName string) string {
|
||||
return common.PropertyGet("caddy", "--global", "image")
|
||||
}
|
||||
|
||||
func reportComputedImage(appName string) string {
|
||||
value := reportGlobalImage(appName)
|
||||
if value == "" {
|
||||
value = dockerfileFromImage("caddy-vhosts")
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func reportGlobalLetsencryptEmail(appName string) string {
|
||||
return common.PropertyGet("caddy", "--global", "letsencrypt-email")
|
||||
}
|
||||
|
||||
func reportComputedLetsencryptEmail(appName string) string {
|
||||
return reportGlobalLetsencryptEmail(appName)
|
||||
}
|
||||
|
||||
func reportGlobalLetsencryptServer(appName string) string {
|
||||
return common.PropertyGet("caddy", "--global", "letsencrypt-server")
|
||||
}
|
||||
|
||||
func reportComputedLetsencryptServer(appName string) string {
|
||||
value := reportGlobalLetsencryptServer(appName)
|
||||
if value == "" {
|
||||
value = "https://acme-v02.api.letsencrypt.org/directory"
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func reportGlobalLogLevel(appName string) string {
|
||||
return common.PropertyGet("caddy", "--global", "log-level")
|
||||
}
|
||||
|
||||
func reportComputedLogLevel(appName string) string {
|
||||
value := reportGlobalLogLevel(appName)
|
||||
if value == "" {
|
||||
value = "ERROR"
|
||||
}
|
||||
|
||||
return strings.ToUpper(value)
|
||||
}
|
||||
|
||||
func reportGlobalPollingInterval(appName string) string {
|
||||
return common.PropertyGet("caddy", "--global", "polling-interval")
|
||||
}
|
||||
|
||||
func reportComputedPollingInterval(appName string) string {
|
||||
value := reportGlobalPollingInterval(appName)
|
||||
if value == "" {
|
||||
value = "5s"
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func reportTLSInternal(appName string) string {
|
||||
return common.PropertyGet("caddy", appName, "tls-internal")
|
||||
}
|
||||
|
||||
func reportGlobalTLSInternal(appName string) string {
|
||||
return common.PropertyGet("caddy", "--global", "tls-internal")
|
||||
}
|
||||
|
||||
func reportComputedTLSInternal(appName string) string {
|
||||
value := reportTLSInternal(appName)
|
||||
if value == "" {
|
||||
value = reportGlobalTLSInternal(appName)
|
||||
}
|
||||
if value == "" {
|
||||
value = "false"
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// dockerfileFromImage returns the image referenced by the FROM line of the named
|
||||
// plugin's Dockerfile, or an empty string when it cannot be read
|
||||
func dockerfileFromImage(pluginName string) string {
|
||||
pluginPath := os.Getenv("PLUGIN_AVAILABLE_PATH")
|
||||
data, err := os.ReadFile(filepath.Join(pluginPath, pluginName, "Dockerfile"))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
if strings.Contains(line, "FROM") {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) >= 2 {
|
||||
return fields[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
40
plugins/caddy-vhosts/src/subcommands/subcommands.go
Normal file
40
plugins/caddy-vhosts/src/subcommands/subcommands.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
caddyvhosts "github.com/dokku/dokku/plugins/caddy-vhosts"
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// main entrypoint to all subcommands
|
||||
func main() {
|
||||
parts := strings.Split(os.Args[0], "/")
|
||||
subcommand := parts[len(parts)-1]
|
||||
|
||||
var err error
|
||||
switch subcommand {
|
||||
case "report":
|
||||
args := flag.NewFlagSet("caddy-vhosts:report", flag.ExitOnError)
|
||||
format := args.String("format", "stdout", "format: [ stdout | json ]")
|
||||
reportArgs, flagErr := common.ParseReportArgs("caddy-vhosts", os.Args[2:])
|
||||
if flagErr == nil {
|
||||
args.Parse(reportArgs.OSArgs)
|
||||
appName := args.Arg(0)
|
||||
if reportArgs.IsGlobal {
|
||||
appName = "--global"
|
||||
}
|
||||
err = caddyvhosts.CommandReport(appName, *format, reportArgs.InfoFlag)
|
||||
}
|
||||
default:
|
||||
err = fmt.Errorf("Invalid plugin subcommand call: %s", subcommand)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
common.LogFailWithError(err)
|
||||
}
|
||||
}
|
||||
31
plugins/caddy-vhosts/src/triggers/triggers.go
Normal file
31
plugins/caddy-vhosts/src/triggers/triggers.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
caddyvhosts "github.com/dokku/dokku/plugins/caddy-vhosts"
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
// main entrypoint to all triggers
|
||||
func main() {
|
||||
parts := strings.Split(os.Args[0], "/")
|
||||
trigger := parts[len(parts)-1]
|
||||
flag.Parse()
|
||||
|
||||
var err error
|
||||
switch trigger {
|
||||
case "report":
|
||||
appName := flag.Arg(0)
|
||||
err = caddyvhosts.ReportSingleApp(appName, "", "")
|
||||
default:
|
||||
err = fmt.Errorf("Invalid plugin trigger call: %s", trigger)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
common.LogFailWithError(err)
|
||||
}
|
||||
}
|
||||
29
plugins/caddy-vhosts/subcommands.go
Normal file
29
plugins/caddy-vhosts/subcommands.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package caddyvhosts
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
// CommandReport displays a caddy-vhosts report for one or more apps
|
||||
func CommandReport(appName string, format string, infoFlag string) error {
|
||||
if len(appName) == 0 {
|
||||
apps, err := common.DokkuApps()
|
||||
if err != nil {
|
||||
if errors.Is(err, common.NoAppsExist) {
|
||||
common.LogWarn(err.Error())
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
for _, appName := range apps {
|
||||
if err := ReportSingleApp(appName, format, infoFlag); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return ReportSingleApp(appName, format, infoFlag)
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$PLUGIN_AVAILABLE_PATH/caddy-vhosts/command-functions"
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
cmd-caddy-report "$@"
|
||||
4
plugins/haproxy-vhosts/.gitignore
vendored
Normal file
4
plugins/haproxy-vhosts/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/report
|
||||
/report-subcommand
|
||||
/triggers
|
||||
/subcommands/report
|
||||
13
plugins/haproxy-vhosts/Makefile
Normal file
13
plugins/haproxy-vhosts/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
GOARCH ?= amd64
|
||||
TRIGGERS = triggers/report
|
||||
BUILD = report-subcommand triggers
|
||||
PLUGIN_NAME = haproxy-vhosts
|
||||
|
||||
clean-report-subcommand:
|
||||
rm -rf report-subcommand
|
||||
|
||||
report-subcommand: clean-report-subcommand src/subcommands/subcommands.go
|
||||
GOARCH=$(GOARCH) go build -mod=readonly -ldflags="-s -w" $(GO_ARGS) -o report-subcommand src/subcommands/subcommands.go
|
||||
ln -sf ../report-subcommand subcommands/report
|
||||
|
||||
include ../../common.mk
|
||||
88
plugins/haproxy-vhosts/command-functions
Executable file → Normal file
88
plugins/haproxy-vhosts/command-functions
Executable file → Normal file
@@ -30,94 +30,6 @@ cmd-haproxy-labels-show() {
|
||||
cmd-proxy-labels-show "proxy:labels:show" "haproxy" "$@"
|
||||
}
|
||||
|
||||
cmd-haproxy-report() {
|
||||
declare desc="displays a haproxy report for one or more apps"
|
||||
declare cmd="haproxy:report"
|
||||
[[ "$1" == "$cmd" ]] && shift 1
|
||||
fn-report-parse-args "$@"
|
||||
set -- "${REPORT_ARGS[@]}"
|
||||
declare APP="${1:-}" INFO_FLAG="${2:-}"
|
||||
|
||||
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
|
||||
INFO_FLAG="$APP"
|
||||
APP=""
|
||||
fi
|
||||
|
||||
if [[ "$REPORT_IS_GLOBAL" == "true" ]]; then
|
||||
APP="--global"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]] && [[ -z "$INFO_FLAG" ]]; then
|
||||
INFO_FLAG="true"
|
||||
fi
|
||||
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
cmd-haproxy-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
elif [[ -z "$APP" ]]; then
|
||||
for app in $(dokku_apps); do
|
||||
cmd-haproxy-report-single "$app" "$INFO_FLAG" "$REPORT_FORMAT" | tee || true
|
||||
done
|
||||
else
|
||||
cmd-haproxy-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd-haproxy-report-single() {
|
||||
declare APP="$1" INFO_FLAG="$2" FORMAT="${3:-stdout}"
|
||||
if [[ "$INFO_FLAG" == "true" ]]; then
|
||||
INFO_FLAG=""
|
||||
fi
|
||||
if [[ "$APP" != "--global" ]]; then
|
||||
verify_app_name "$APP"
|
||||
fi
|
||||
local flag_map=(
|
||||
"--haproxy-computed-image: $(fn-haproxy-computed-image)"
|
||||
"--haproxy-computed-letsencrypt-email: $(fn-haproxy-computed-letsencrypt-email)"
|
||||
"--haproxy-computed-letsencrypt-server: $(fn-haproxy-computed-letsencrypt-server)"
|
||||
"--haproxy-computed-log-level: $(fn-haproxy-computed-log-level)"
|
||||
"--haproxy-computed-refresh-conf: $(fn-haproxy-computed-refresh-conf)"
|
||||
"--haproxy-global-image: $(fn-haproxy-global-image)"
|
||||
"--haproxy-global-letsencrypt-email: $(fn-haproxy-global-letsencrypt-email)"
|
||||
"--haproxy-global-letsencrypt-server: $(fn-haproxy-global-letsencrypt-server)"
|
||||
"--haproxy-global-log-level: $(fn-haproxy-global-log-level)"
|
||||
"--haproxy-global-refresh-conf: $(fn-haproxy-global-refresh-conf)"
|
||||
)
|
||||
|
||||
fn-report-validate-format "$FORMAT" "$INFO_FLAG"
|
||||
|
||||
if [[ "$FORMAT" == "json" ]]; then
|
||||
fn-report-emit-json flag_map "haproxy"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "$INFO_FLAG" ]]; then
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
dokku_log_info2_quiet "global haproxy information"
|
||||
else
|
||||
dokku_log_info2_quiet "${APP} haproxy information"
|
||||
fi
|
||||
for flag in "${flag_map[@]}"; do
|
||||
key="$(echo "${flag#--}" | cut -f1 -d' ' | tr - ' ')"
|
||||
dokku_log_verbose "$(printf "%-30s %-25s" "${key^}" "${flag#*: }")"
|
||||
done
|
||||
else
|
||||
local match=false
|
||||
for flag in "${flag_map[@]}"; do
|
||||
valid_flags="${valid_flags} $(echo "$flag" | cut -d':' -f1)"
|
||||
if [[ "$flag" == "${INFO_FLAG}:"* ]]; then
|
||||
value=${flag#*: }
|
||||
size="${#value}"
|
||||
if [[ "$size" -ne 0 ]]; then
|
||||
echo "$value" && match=true
|
||||
else
|
||||
match=true
|
||||
fi
|
||||
fi
|
||||
done
|
||||
[[ "$match" == "true" ]] || dokku_log_fail "Invalid flag passed, valid flags:${valid_flags}"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd-haproxy-logs() {
|
||||
declare desc="display haproxy logs from command line"
|
||||
declare cmd="haproxy:logs"
|
||||
|
||||
29
plugins/haproxy-vhosts/go.mod
Normal file
29
plugins/haproxy-vhosts/go.mod
Normal file
@@ -0,0 +1,29 @@
|
||||
module github.com/dokku/dokku/plugins/haproxy-vhosts
|
||||
|
||||
go 1.26.2
|
||||
|
||||
require (
|
||||
github.com/dokku/dokku/plugins/common v0.0.0-00010101000000-000000000000
|
||||
github.com/spf13/pflag v1.0.10
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/fatih/color v1.19.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/melbahja/goph v1.5.1 // indirect
|
||||
github.com/otiai10/copy v1.14.1 // indirect
|
||||
github.com/otiai10/mint v1.6.3 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/sftp v1.13.10 // indirect
|
||||
github.com/ryanuber/columnize v2.1.2+incompatible // indirect
|
||||
golang.org/x/crypto v0.53.0 // indirect
|
||||
golang.org/x/sync v0.21.0 // indirect
|
||||
golang.org/x/sys v0.46.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/dokku/dokku/plugins/common => ../common
|
||||
55
plugins/haproxy-vhosts/go.sum
Normal file
55
plugins/haproxy-vhosts/go.sum
Normal file
@@ -0,0 +1,55 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w=
|
||||
github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/melbahja/goph v1.5.1 h1:gdZyjn5nM6FO6mAZrv7XqE2gArQbb+V6FdIyH3Ru3vA=
|
||||
github.com/melbahja/goph v1.5.1/go.mod h1:dDwo+44cmvfDLdiVpc6fJxexf5BA5yEDUeE5YgtuDO4=
|
||||
github.com/onsi/gomega v1.42.1 h1:iN1rCUX+44NZ1Dc97MPoeFYbFR0vh8zxoxMFwKdyZ6I=
|
||||
github.com/onsi/gomega v1.42.1/go.mod h1:REff/hsDsodHoKlWsP2mAPhu1+5/6hVYNf9rIEBpeSg=
|
||||
github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8=
|
||||
github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I=
|
||||
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=
|
||||
github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.10 h1:+5FbKNTe5Z9aspU88DPIKJ9z2KZoaGCu6Sr6kKR/5mU=
|
||||
github.com/pkg/sftp v1.13.10/go.mod h1:bJ1a7uDhrX/4OII+agvy28lzRvQrmIQuaHrcI1HbeGA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/ryanuber/columnize v2.1.2+incompatible h1:C89EOx/XBWwIXl8wm8OPJBd7kPF25UfsK2X7Ph/zCAk=
|
||||
github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
|
||||
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
|
||||
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
|
||||
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
|
||||
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
|
||||
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
|
||||
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
|
||||
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
|
||||
golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
|
||||
golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$PLUGIN_AVAILABLE_PATH/haproxy-vhosts/command-functions"
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
cmd-haproxy-report-single "$@"
|
||||
130
plugins/haproxy-vhosts/report.go
Normal file
130
plugins/haproxy-vhosts/report.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package haproxyvhosts
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
// ReportSingleApp is an internal function that displays the haproxy report for one or more apps
|
||||
func ReportSingleApp(appName string, format string, infoFlag string) error {
|
||||
if appName != "--global" {
|
||||
if err := common.VerifyAppName(appName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
flags := map[string]common.ReportFunc{
|
||||
"--haproxy-computed-image": reportComputedImage,
|
||||
"--haproxy-computed-letsencrypt-email": reportComputedLetsencryptEmail,
|
||||
"--haproxy-computed-letsencrypt-server": reportComputedLetsencryptServer,
|
||||
"--haproxy-computed-log-level": reportComputedLogLevel,
|
||||
"--haproxy-computed-refresh-conf": reportComputedRefreshConf,
|
||||
"--haproxy-global-image": reportGlobalImage,
|
||||
"--haproxy-global-letsencrypt-email": reportGlobalLetsencryptEmail,
|
||||
"--haproxy-global-letsencrypt-server": reportGlobalLetsencryptServer,
|
||||
"--haproxy-global-log-level": reportGlobalLogLevel,
|
||||
"--haproxy-global-refresh-conf": reportGlobalRefreshConf,
|
||||
}
|
||||
|
||||
flagKeys := []string{}
|
||||
for flagKey := range flags {
|
||||
flagKeys = append(flagKeys, flagKey)
|
||||
}
|
||||
|
||||
infoFlags := common.CollectReport(appName, infoFlag, flags)
|
||||
return common.ReportSingleApp(common.ReportSingleAppInput{
|
||||
ReportType: "haproxy",
|
||||
AppName: appName,
|
||||
InfoFlag: infoFlag,
|
||||
InfoFlags: infoFlags,
|
||||
InfoFlagKeys: flagKeys,
|
||||
Format: format,
|
||||
TrimPrefix: true,
|
||||
UppercaseFirstCharacter: true,
|
||||
EmitLegacyPrefix: false,
|
||||
})
|
||||
}
|
||||
|
||||
func reportGlobalImage(appName string) string {
|
||||
return common.PropertyGet("haproxy", "--global", "image")
|
||||
}
|
||||
|
||||
func reportComputedImage(appName string) string {
|
||||
value := reportGlobalImage(appName)
|
||||
if value == "" {
|
||||
value = dockerfileFromImage("haproxy-vhosts")
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func reportGlobalLetsencryptEmail(appName string) string {
|
||||
return common.PropertyGet("haproxy", "--global", "letsencrypt-email")
|
||||
}
|
||||
|
||||
func reportComputedLetsencryptEmail(appName string) string {
|
||||
return reportGlobalLetsencryptEmail(appName)
|
||||
}
|
||||
|
||||
func reportGlobalLetsencryptServer(appName string) string {
|
||||
return common.PropertyGet("haproxy", "--global", "letsencrypt-server")
|
||||
}
|
||||
|
||||
func reportComputedLetsencryptServer(appName string) string {
|
||||
value := reportGlobalLetsencryptServer(appName)
|
||||
if value == "" {
|
||||
value = "https://acme-v02.api.letsencrypt.org/directory"
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func reportGlobalLogLevel(appName string) string {
|
||||
return common.PropertyGet("haproxy", "--global", "log-level")
|
||||
}
|
||||
|
||||
func reportComputedLogLevel(appName string) string {
|
||||
value := reportGlobalLogLevel(appName)
|
||||
if value == "" {
|
||||
value = "ERROR"
|
||||
}
|
||||
|
||||
return strings.ToUpper(value)
|
||||
}
|
||||
|
||||
func reportGlobalRefreshConf(appName string) string {
|
||||
return common.PropertyGet("haproxy", "--global", "refresh-conf")
|
||||
}
|
||||
|
||||
func reportComputedRefreshConf(appName string) string {
|
||||
value := reportGlobalRefreshConf(appName)
|
||||
if value == "" {
|
||||
value = "10"
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// dockerfileFromImage returns the image referenced by the FROM line of the named
|
||||
// plugin's Dockerfile, or an empty string when it cannot be read
|
||||
func dockerfileFromImage(pluginName string) string {
|
||||
pluginPath := os.Getenv("PLUGIN_AVAILABLE_PATH")
|
||||
data, err := os.ReadFile(filepath.Join(pluginPath, pluginName, "Dockerfile"))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
if strings.Contains(line, "FROM") {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) >= 2 {
|
||||
return fields[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
40
plugins/haproxy-vhosts/src/subcommands/subcommands.go
Normal file
40
plugins/haproxy-vhosts/src/subcommands/subcommands.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
haproxyvhosts "github.com/dokku/dokku/plugins/haproxy-vhosts"
|
||||
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// main entrypoint to all subcommands
|
||||
func main() {
|
||||
parts := strings.Split(os.Args[0], "/")
|
||||
subcommand := parts[len(parts)-1]
|
||||
|
||||
var err error
|
||||
switch subcommand {
|
||||
case "report":
|
||||
args := flag.NewFlagSet("haproxy-vhosts:report", flag.ExitOnError)
|
||||
format := args.String("format", "stdout", "format: [ stdout | json ]")
|
||||
reportArgs, flagErr := common.ParseReportArgs("haproxy-vhosts", os.Args[2:])
|
||||
if flagErr == nil {
|
||||
args.Parse(reportArgs.OSArgs)
|
||||
appName := args.Arg(0)
|
||||
if reportArgs.IsGlobal {
|
||||
appName = "--global"
|
||||
}
|
||||
err = haproxyvhosts.CommandReport(appName, *format, reportArgs.InfoFlag)
|
||||
}
|
||||
default:
|
||||
err = fmt.Errorf("Invalid plugin subcommand call: %s", subcommand)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
common.LogFailWithError(err)
|
||||
}
|
||||
}
|
||||
31
plugins/haproxy-vhosts/src/triggers/triggers.go
Normal file
31
plugins/haproxy-vhosts/src/triggers/triggers.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
haproxyvhosts "github.com/dokku/dokku/plugins/haproxy-vhosts"
|
||||
)
|
||||
|
||||
// main entrypoint to all triggers
|
||||
func main() {
|
||||
parts := strings.Split(os.Args[0], "/")
|
||||
trigger := parts[len(parts)-1]
|
||||
flag.Parse()
|
||||
|
||||
var err error
|
||||
switch trigger {
|
||||
case "report":
|
||||
appName := flag.Arg(0)
|
||||
err = haproxyvhosts.ReportSingleApp(appName, "", "")
|
||||
default:
|
||||
err = fmt.Errorf("Invalid plugin trigger call: %s", trigger)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
common.LogFailWithError(err)
|
||||
}
|
||||
}
|
||||
29
plugins/haproxy-vhosts/subcommands.go
Normal file
29
plugins/haproxy-vhosts/subcommands.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package haproxyvhosts
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
// CommandReport displays a haproxy-vhosts report for one or more apps
|
||||
func CommandReport(appName string, format string, infoFlag string) error {
|
||||
if len(appName) == 0 {
|
||||
apps, err := common.DokkuApps()
|
||||
if err != nil {
|
||||
if errors.Is(err, common.NoAppsExist) {
|
||||
common.LogWarn(err.Error())
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
for _, appName := range apps {
|
||||
if err := ReportSingleApp(appName, format, infoFlag); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return ReportSingleApp(appName, format, infoFlag)
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$PLUGIN_AVAILABLE_PATH/haproxy-vhosts/command-functions"
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
cmd-haproxy-report "$@"
|
||||
4
plugins/openresty-vhosts/.gitignore
vendored
Normal file
4
plugins/openresty-vhosts/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/report
|
||||
/report-subcommand
|
||||
/triggers
|
||||
/subcommands/report
|
||||
13
plugins/openresty-vhosts/Makefile
Normal file
13
plugins/openresty-vhosts/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
GOARCH ?= amd64
|
||||
TRIGGERS = triggers/report
|
||||
BUILD = report-subcommand triggers
|
||||
PLUGIN_NAME = openresty-vhosts
|
||||
|
||||
clean-report-subcommand:
|
||||
rm -rf report-subcommand
|
||||
|
||||
report-subcommand: clean-report-subcommand src/subcommands/subcommands.go
|
||||
GOARCH=$(GOARCH) go build -mod=readonly -ldflags="-s -w" $(GO_ARGS) -o report-subcommand src/subcommands/subcommands.go
|
||||
ln -sf ../report-subcommand subcommands/report
|
||||
|
||||
include ../../common.mk
|
||||
237
plugins/openresty-vhosts/command-functions
Executable file → Normal file
237
plugins/openresty-vhosts/command-functions
Executable file → Normal file
@@ -30,243 +30,6 @@ cmd-openresty-labels-show() {
|
||||
cmd-proxy-labels-show "proxy:labels:show" "openresty" "$@"
|
||||
}
|
||||
|
||||
cmd-openresty-report() {
|
||||
declare desc="displays a openresty report for one or more apps"
|
||||
declare cmd="openresty:report"
|
||||
[[ "$1" == "$cmd" ]] && shift 1
|
||||
fn-report-parse-args "$@"
|
||||
set -- "${REPORT_ARGS[@]}"
|
||||
declare APP="${1:-}" INFO_FLAG="${2:-}"
|
||||
|
||||
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
|
||||
INFO_FLAG="$APP"
|
||||
APP=""
|
||||
fi
|
||||
|
||||
if [[ "$REPORT_IS_GLOBAL" == "true" ]]; then
|
||||
APP="--global"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]] && [[ -z "$INFO_FLAG" ]]; then
|
||||
INFO_FLAG="true"
|
||||
fi
|
||||
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
cmd-openresty-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
elif [[ -z "$APP" ]]; then
|
||||
for app in $(dokku_apps); do
|
||||
cmd-openresty-report-single "$app" "$INFO_FLAG" "$REPORT_FORMAT" | tee || true
|
||||
done
|
||||
else
|
||||
cmd-openresty-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd-openresty-report-single() {
|
||||
declare APP="$1" INFO_FLAG="$2" FORMAT="${3:-stdout}"
|
||||
if [[ "$INFO_FLAG" == "true" ]]; then
|
||||
INFO_FLAG=""
|
||||
fi
|
||||
local flag_map=()
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
flag_map=(
|
||||
"--openresty-global-access-log-format: $(fn-openresty-global-access-log-format)"
|
||||
"--openresty-computed-access-log-format: $(fn-openresty-computed-access-log-format "$APP")"
|
||||
"--openresty-global-access-log-path: $(fn-openresty-global-access-log-path)"
|
||||
"--openresty-computed-access-log-path: $(fn-openresty-computed-access-log-path "$APP")"
|
||||
"--openresty-global-allowed-letsencrypt-domains-func-base64: $(fn-openresty-global-allowed-letsencrypt-domains-func-base64)"
|
||||
"--openresty-computed-allowed-letsencrypt-domains-func-base64: $(fn-openresty-computed-allowed-letsencrypt-domains-func-base64)"
|
||||
"--openresty-global-bind-address-ipv4: $(fn-openresty-global-bind-address-ipv4)"
|
||||
"--openresty-computed-bind-address-ipv4: $(fn-openresty-computed-bind-address-ipv4 "$APP")"
|
||||
"--openresty-global-bind-address-ipv6: $(fn-openresty-global-bind-address-ipv6)"
|
||||
"--openresty-computed-bind-address-ipv6: $(fn-openresty-computed-bind-address-ipv6 "$APP")"
|
||||
"--openresty-global-client-body-timeout: $(fn-openresty-global-client-body-timeout)"
|
||||
"--openresty-computed-client-body-timeout: $(fn-openresty-computed-client-body-timeout "$APP")"
|
||||
"--openresty-global-client-header-timeout: $(fn-openresty-global-client-header-timeout)"
|
||||
"--openresty-computed-client-header-timeout: $(fn-openresty-computed-client-header-timeout "$APP")"
|
||||
"--openresty-global-client-max-body-size: $(fn-openresty-global-client-max-body-size)"
|
||||
"--openresty-computed-client-max-body-size: $(fn-openresty-computed-client-max-body-size "$APP")"
|
||||
"--openresty-global-error-log-path: $(fn-openresty-global-error-log-path)"
|
||||
"--openresty-computed-error-log-path: $(fn-openresty-computed-error-log-path "$APP")"
|
||||
"--openresty-global-hsts: $(fn-plugin-property-get-default "openresty" "--global" "hsts" "")"
|
||||
"--openresty-computed-hsts: $(fn-openresty-hsts-is-enabled "--global")"
|
||||
"--openresty-global-hsts-include-subdomains: $(fn-openresty-global-hsts-include-subdomains)"
|
||||
"--openresty-computed-hsts-include-subdomains: $(fn-openresty-computed-hsts-include-subdomains "$APP")"
|
||||
"--openresty-global-hsts-max-age: $(fn-openresty-global-hsts-max-age)"
|
||||
"--openresty-computed-hsts-max-age: $(fn-openresty-computed-hsts-max-age "$APP")"
|
||||
"--openresty-global-hsts-preload: $(fn-openresty-global-hsts-preload)"
|
||||
"--openresty-computed-hsts-preload: $(fn-openresty-computed-hsts-preload "$APP")"
|
||||
"--openresty-global-image: $(fn-openresty-global-image)"
|
||||
"--openresty-computed-image: $(fn-openresty-computed-image)"
|
||||
"--openresty-global-keepalive-timeout: $(fn-openresty-global-keepalive-timeout)"
|
||||
"--openresty-computed-keepalive-timeout: $(fn-openresty-computed-keepalive-timeout "$APP")"
|
||||
"--openresty-global-letsencrypt-email: $(fn-openresty-global-letsencrypt-email)"
|
||||
"--openresty-computed-letsencrypt-email: $(fn-openresty-computed-letsencrypt-email)"
|
||||
"--openresty-global-letsencrypt-server: $(fn-openresty-global-letsencrypt-server)"
|
||||
"--openresty-computed-letsencrypt-server: $(fn-openresty-computed-letsencrypt-server)"
|
||||
"--openresty-global-lingering-timeout: $(fn-openresty-global-lingering-timeout)"
|
||||
"--openresty-computed-lingering-timeout: $(fn-openresty-computed-lingering-timeout "$APP")"
|
||||
"--openresty-global-log-level: $(fn-openresty-global-log-level)"
|
||||
"--openresty-computed-log-level: $(fn-openresty-computed-log-level)"
|
||||
"--openresty-global-proxy-buffer-size: $(fn-openresty-global-proxy-buffer-size)"
|
||||
"--openresty-computed-proxy-buffer-size: $(fn-openresty-computed-proxy-buffer-size "$APP")"
|
||||
"--openresty-global-proxy-buffering: $(fn-openresty-global-proxy-buffering)"
|
||||
"--openresty-computed-proxy-buffering: $(fn-openresty-computed-proxy-buffering "$APP")"
|
||||
"--openresty-global-proxy-buffers: $(fn-openresty-global-proxy-buffers)"
|
||||
"--openresty-computed-proxy-buffers: $(fn-openresty-computed-proxy-buffers "$APP")"
|
||||
"--openresty-global-proxy-busy-buffers-size: $(fn-openresty-global-proxy-busy-buffers-size)"
|
||||
"--openresty-computed-proxy-busy-buffers-size: $(fn-openresty-computed-proxy-busy-buffers-size "$APP")"
|
||||
"--openresty-global-proxy-connect-timeout: $(fn-openresty-global-proxy-connect-timeout)"
|
||||
"--openresty-computed-proxy-connect-timeout: $(fn-openresty-computed-proxy-connect-timeout "$APP")"
|
||||
"--openresty-global-proxy-read-timeout: $(fn-openresty-global-proxy-read-timeout)"
|
||||
"--openresty-computed-proxy-read-timeout: $(fn-openresty-computed-proxy-read-timeout "$APP")"
|
||||
"--openresty-global-proxy-send-timeout: $(fn-openresty-global-proxy-send-timeout)"
|
||||
"--openresty-computed-proxy-send-timeout: $(fn-openresty-computed-proxy-send-timeout "$APP")"
|
||||
"--openresty-global-send-timeout: $(fn-openresty-global-send-timeout)"
|
||||
"--openresty-computed-send-timeout: $(fn-openresty-computed-send-timeout "$APP")"
|
||||
"--openresty-global-underscore-in-headers: $(fn-openresty-global-underscore-in-headers)"
|
||||
"--openresty-computed-underscore-in-headers: $(fn-openresty-computed-underscore-in-headers "$APP")"
|
||||
"--openresty-global-x-forwarded-for-value: $(fn-openresty-global-x-forwarded-for-value)"
|
||||
"--openresty-computed-x-forwarded-for-value: $(fn-openresty-computed-x-forwarded-for-value "$APP")"
|
||||
"--openresty-global-x-forwarded-port-value: $(fn-openresty-global-x-forwarded-port-value)"
|
||||
"--openresty-computed-x-forwarded-port-value: $(fn-openresty-computed-x-forwarded-port-value "$APP")"
|
||||
"--openresty-global-x-forwarded-proto-value: $(fn-openresty-global-x-forwarded-proto-value)"
|
||||
"--openresty-computed-x-forwarded-proto-value: $(fn-openresty-computed-x-forwarded-proto-value "$APP")"
|
||||
"--openresty-global-x-forwarded-ssl: $(fn-openresty-global-x-forwarded-ssl)"
|
||||
"--openresty-computed-x-forwarded-ssl: $(fn-openresty-computed-x-forwarded-ssl "$APP")"
|
||||
)
|
||||
else
|
||||
verify_app_name "$APP"
|
||||
flag_map=(
|
||||
"--openresty-access-log-format: $(fn-openresty-access-log-format "$APP")"
|
||||
"--openresty-computed-access-log-format: $(fn-openresty-computed-access-log-format "$APP")"
|
||||
"--openresty-global-access-log-format: $(fn-openresty-global-access-log-format)"
|
||||
"--openresty-access-log-path: $(fn-openresty-access-log-path "$APP")"
|
||||
"--openresty-computed-access-log-path: $(fn-openresty-computed-access-log-path "$APP")"
|
||||
"--openresty-global-access-log-path: $(fn-openresty-global-access-log-path)"
|
||||
"--openresty-global-allowed-letsencrypt-domains-func-base64: $(fn-openresty-global-allowed-letsencrypt-domains-func-base64)"
|
||||
"--openresty-computed-allowed-letsencrypt-domains-func-base64: $(fn-openresty-computed-allowed-letsencrypt-domains-func-base64)"
|
||||
"--openresty-bind-address-ipv4: $(fn-openresty-bind-address-ipv4 "$APP")"
|
||||
"--openresty-computed-bind-address-ipv4: $(fn-openresty-computed-bind-address-ipv4 "$APP")"
|
||||
"--openresty-global-bind-address-ipv4: $(fn-openresty-global-bind-address-ipv4)"
|
||||
"--openresty-bind-address-ipv6: $(fn-openresty-bind-address-ipv6 "$APP")"
|
||||
"--openresty-computed-bind-address-ipv6: $(fn-openresty-computed-bind-address-ipv6 "$APP")"
|
||||
"--openresty-global-bind-address-ipv6: $(fn-openresty-global-bind-address-ipv6)"
|
||||
"--openresty-client-body-timeout: $(fn-openresty-client-body-timeout "$APP")"
|
||||
"--openresty-computed-client-body-timeout: $(fn-openresty-computed-client-body-timeout "$APP")"
|
||||
"--openresty-global-client-body-timeout: $(fn-openresty-global-client-body-timeout)"
|
||||
"--openresty-client-header-timeout: $(fn-openresty-client-header-timeout "$APP")"
|
||||
"--openresty-computed-client-header-timeout: $(fn-openresty-computed-client-header-timeout "$APP")"
|
||||
"--openresty-global-client-header-timeout: $(fn-openresty-global-client-header-timeout)"
|
||||
"--openresty-client-max-body-size: $(fn-openresty-client-max-body-size "$APP")"
|
||||
"--openresty-computed-client-max-body-size: $(fn-openresty-computed-client-max-body-size "$APP")"
|
||||
"--openresty-global-client-max-body-size: $(fn-openresty-global-client-max-body-size)"
|
||||
"--openresty-error-log-path: $(fn-openresty-error-log-path "$APP")"
|
||||
"--openresty-computed-error-log-path: $(fn-openresty-computed-error-log-path "$APP")"
|
||||
"--openresty-global-error-log-path: $(fn-openresty-global-error-log-path)"
|
||||
"--openresty-hsts: $(fn-plugin-property-get-default "openresty" "$APP" "hsts" "")"
|
||||
"--openresty-computed-hsts: $(fn-openresty-hsts-is-enabled "$APP")"
|
||||
"--openresty-global-hsts: $(fn-plugin-property-get-default "openresty" "--global" "hsts" "")"
|
||||
"--openresty-hsts-include-subdomains: $(fn-openresty-hsts-include-subdomains "$APP")"
|
||||
"--openresty-computed-hsts-include-subdomains: $(fn-openresty-computed-hsts-include-subdomains "$APP")"
|
||||
"--openresty-global-hsts-include-subdomains: $(fn-openresty-global-hsts-include-subdomains)"
|
||||
"--openresty-hsts-max-age: $(fn-openresty-hsts-max-age "$APP")"
|
||||
"--openresty-computed-hsts-max-age: $(fn-openresty-computed-hsts-max-age "$APP")"
|
||||
"--openresty-global-hsts-max-age: $(fn-openresty-global-hsts-max-age)"
|
||||
"--openresty-hsts-preload: $(fn-openresty-hsts-preload "$APP")"
|
||||
"--openresty-computed-hsts-preload: $(fn-openresty-computed-hsts-preload "$APP")"
|
||||
"--openresty-global-hsts-preload: $(fn-openresty-global-hsts-preload)"
|
||||
"--openresty-global-image: $(fn-openresty-global-image)"
|
||||
"--openresty-computed-image: $(fn-openresty-computed-image)"
|
||||
"--openresty-keepalive-timeout: $(fn-openresty-keepalive-timeout "$APP")"
|
||||
"--openresty-computed-keepalive-timeout: $(fn-openresty-computed-keepalive-timeout "$APP")"
|
||||
"--openresty-global-keepalive-timeout: $(fn-openresty-global-keepalive-timeout)"
|
||||
"--openresty-global-letsencrypt-email: $(fn-openresty-global-letsencrypt-email)"
|
||||
"--openresty-computed-letsencrypt-email: $(fn-openresty-computed-letsencrypt-email)"
|
||||
"--openresty-global-letsencrypt-server: $(fn-openresty-global-letsencrypt-server)"
|
||||
"--openresty-computed-letsencrypt-server: $(fn-openresty-computed-letsencrypt-server)"
|
||||
"--openresty-lingering-timeout: $(fn-openresty-lingering-timeout "$APP")"
|
||||
"--openresty-computed-lingering-timeout: $(fn-openresty-computed-lingering-timeout "$APP")"
|
||||
"--openresty-global-lingering-timeout: $(fn-openresty-global-lingering-timeout)"
|
||||
"--openresty-global-log-level: $(fn-openresty-global-log-level)"
|
||||
"--openresty-computed-log-level: $(fn-openresty-computed-log-level)"
|
||||
"--openresty-proxy-buffer-size: $(fn-openresty-proxy-buffer-size "$APP")"
|
||||
"--openresty-computed-proxy-buffer-size: $(fn-openresty-computed-proxy-buffer-size "$APP")"
|
||||
"--openresty-global-proxy-buffer-size: $(fn-openresty-global-proxy-buffer-size)"
|
||||
"--openresty-proxy-buffering: $(fn-openresty-proxy-buffering "$APP")"
|
||||
"--openresty-computed-proxy-buffering: $(fn-openresty-computed-proxy-buffering "$APP")"
|
||||
"--openresty-global-proxy-buffering: $(fn-openresty-global-proxy-buffering)"
|
||||
"--openresty-proxy-buffers: $(fn-openresty-proxy-buffers "$APP")"
|
||||
"--openresty-computed-proxy-buffers: $(fn-openresty-computed-proxy-buffers "$APP")"
|
||||
"--openresty-global-proxy-buffers: $(fn-openresty-global-proxy-buffers)"
|
||||
"--openresty-proxy-busy-buffers-size: $(fn-openresty-proxy-busy-buffers-size "$APP")"
|
||||
"--openresty-computed-proxy-busy-buffers-size: $(fn-openresty-computed-proxy-busy-buffers-size "$APP")"
|
||||
"--openresty-global-proxy-busy-buffers-size: $(fn-openresty-global-proxy-busy-buffers-size)"
|
||||
"--openresty-proxy-connect-timeout: $(fn-openresty-proxy-connect-timeout "$APP")"
|
||||
"--openresty-computed-proxy-connect-timeout: $(fn-openresty-computed-proxy-connect-timeout "$APP")"
|
||||
"--openresty-global-proxy-connect-timeout: $(fn-openresty-global-proxy-connect-timeout)"
|
||||
"--openresty-proxy-read-timeout: $(fn-openresty-proxy-read-timeout "$APP")"
|
||||
"--openresty-computed-proxy-read-timeout: $(fn-openresty-computed-proxy-read-timeout "$APP")"
|
||||
"--openresty-global-proxy-read-timeout: $(fn-openresty-global-proxy-read-timeout)"
|
||||
"--openresty-proxy-send-timeout: $(fn-openresty-proxy-send-timeout "$APP")"
|
||||
"--openresty-computed-proxy-send-timeout: $(fn-openresty-computed-proxy-send-timeout "$APP")"
|
||||
"--openresty-global-proxy-send-timeout: $(fn-openresty-global-proxy-send-timeout)"
|
||||
"--openresty-send-timeout: $(fn-openresty-send-timeout "$APP")"
|
||||
"--openresty-computed-send-timeout: $(fn-openresty-computed-send-timeout "$APP")"
|
||||
"--openresty-global-send-timeout: $(fn-openresty-global-send-timeout)"
|
||||
"--openresty-underscore-in-headers: $(fn-openresty-underscore-in-headers "$APP")"
|
||||
"--openresty-computed-underscore-in-headers: $(fn-openresty-computed-underscore-in-headers "$APP")"
|
||||
"--openresty-global-underscore-in-headers: $(fn-openresty-global-underscore-in-headers)"
|
||||
"--openresty-x-forwarded-for-value: $(fn-openresty-x-forwarded-for-value "$APP")"
|
||||
"--openresty-computed-x-forwarded-for-value: $(fn-openresty-computed-x-forwarded-for-value "$APP")"
|
||||
"--openresty-global-x-forwarded-for-value: $(fn-openresty-global-x-forwarded-for-value)"
|
||||
"--openresty-x-forwarded-port-value: $(fn-openresty-x-forwarded-port-value "$APP")"
|
||||
"--openresty-computed-x-forwarded-port-value: $(fn-openresty-computed-x-forwarded-port-value "$APP")"
|
||||
"--openresty-global-x-forwarded-port-value: $(fn-openresty-global-x-forwarded-port-value)"
|
||||
"--openresty-x-forwarded-proto-value: $(fn-openresty-x-forwarded-proto-value "$APP")"
|
||||
"--openresty-computed-x-forwarded-proto-value: $(fn-openresty-computed-x-forwarded-proto-value "$APP")"
|
||||
"--openresty-global-x-forwarded-proto-value: $(fn-openresty-global-x-forwarded-proto-value)"
|
||||
"--openresty-x-forwarded-ssl: $(fn-openresty-x-forwarded-ssl "$APP")"
|
||||
"--openresty-computed-x-forwarded-ssl: $(fn-openresty-computed-x-forwarded-ssl "$APP")"
|
||||
"--openresty-global-x-forwarded-ssl: $(fn-openresty-global-x-forwarded-ssl)"
|
||||
)
|
||||
fi
|
||||
|
||||
fn-report-validate-format "$FORMAT" "$INFO_FLAG"
|
||||
|
||||
if [[ "$FORMAT" == "json" ]]; then
|
||||
fn-report-emit-json flag_map "openresty"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "$INFO_FLAG" ]]; then
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
dokku_log_info2_quiet "global openresty information"
|
||||
else
|
||||
dokku_log_info2_quiet "${APP} openresty information"
|
||||
fi
|
||||
for flag in "${flag_map[@]}"; do
|
||||
key="$(echo "${flag#--}" | cut -f1 -d' ' | tr - ' ')"
|
||||
dokku_log_verbose "$(printf "%-30s %-25s" "${key^}" "${flag#*: }")"
|
||||
done
|
||||
else
|
||||
local match=false
|
||||
for flag in "${flag_map[@]}"; do
|
||||
valid_flags="${valid_flags} $(echo "$flag" | cut -d':' -f1)"
|
||||
if [[ "$flag" == "${INFO_FLAG}:"* ]]; then
|
||||
value=${flag#*: }
|
||||
size="${#value}"
|
||||
if [[ "$size" -ne 0 ]]; then
|
||||
echo "$value" && match=true
|
||||
else
|
||||
match=true
|
||||
fi
|
||||
fi
|
||||
done
|
||||
[[ "$match" == "true" ]] || dokku_log_fail "Invalid flag passed, valid flags:${valid_flags}"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd-openresty-logs() {
|
||||
declare desc="display openresty logs from command line"
|
||||
declare cmd="openresty:logs"
|
||||
|
||||
29
plugins/openresty-vhosts/go.mod
Normal file
29
plugins/openresty-vhosts/go.mod
Normal file
@@ -0,0 +1,29 @@
|
||||
module github.com/dokku/dokku/plugins/openresty-vhosts
|
||||
|
||||
go 1.26.2
|
||||
|
||||
require (
|
||||
github.com/dokku/dokku/plugins/common v0.0.0-00010101000000-000000000000
|
||||
github.com/spf13/pflag v1.0.10
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/fatih/color v1.19.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/melbahja/goph v1.5.1 // indirect
|
||||
github.com/otiai10/copy v1.14.1 // indirect
|
||||
github.com/otiai10/mint v1.6.3 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/sftp v1.13.10 // indirect
|
||||
github.com/ryanuber/columnize v2.1.2+incompatible // indirect
|
||||
golang.org/x/crypto v0.53.0 // indirect
|
||||
golang.org/x/sync v0.21.0 // indirect
|
||||
golang.org/x/sys v0.46.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/dokku/dokku/plugins/common => ../common
|
||||
55
plugins/openresty-vhosts/go.sum
Normal file
55
plugins/openresty-vhosts/go.sum
Normal file
@@ -0,0 +1,55 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w=
|
||||
github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/melbahja/goph v1.5.1 h1:gdZyjn5nM6FO6mAZrv7XqE2gArQbb+V6FdIyH3Ru3vA=
|
||||
github.com/melbahja/goph v1.5.1/go.mod h1:dDwo+44cmvfDLdiVpc6fJxexf5BA5yEDUeE5YgtuDO4=
|
||||
github.com/onsi/gomega v1.42.1 h1:iN1rCUX+44NZ1Dc97MPoeFYbFR0vh8zxoxMFwKdyZ6I=
|
||||
github.com/onsi/gomega v1.42.1/go.mod h1:REff/hsDsodHoKlWsP2mAPhu1+5/6hVYNf9rIEBpeSg=
|
||||
github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8=
|
||||
github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I=
|
||||
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=
|
||||
github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.10 h1:+5FbKNTe5Z9aspU88DPIKJ9z2KZoaGCu6Sr6kKR/5mU=
|
||||
github.com/pkg/sftp v1.13.10/go.mod h1:bJ1a7uDhrX/4OII+agvy28lzRvQrmIQuaHrcI1HbeGA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/ryanuber/columnize v2.1.2+incompatible h1:C89EOx/XBWwIXl8wm8OPJBd7kPF25UfsK2X7Ph/zCAk=
|
||||
github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
|
||||
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
|
||||
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
|
||||
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
|
||||
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
|
||||
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
|
||||
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
|
||||
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
|
||||
golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
|
||||
golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$PLUGIN_AVAILABLE_PATH/openresty-vhosts/command-functions"
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
cmd-openresty-report-single "$@"
|
||||
173
plugins/openresty-vhosts/report.go
Normal file
173
plugins/openresty-vhosts/report.go
Normal file
@@ -0,0 +1,173 @@
|
||||
package openrestyvhosts
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
const openrestyLogRoot = "/var/log/nginx"
|
||||
|
||||
// openrestyProp describes a settable openresty property along with the computed
|
||||
// default used when neither an app-scoped nor a global value is present.
|
||||
type openrestyProp struct {
|
||||
name string
|
||||
hasApp bool
|
||||
computedDefault func(appName string) string
|
||||
}
|
||||
|
||||
func staticDefault(value string) func(string) string {
|
||||
return func(string) string { return value }
|
||||
}
|
||||
|
||||
func openrestyPageSizeKB() int {
|
||||
return os.Getpagesize() / 1024
|
||||
}
|
||||
|
||||
func openrestyProps() []openrestyProp {
|
||||
pageSize := openrestyPageSizeKB()
|
||||
return []openrestyProp{
|
||||
{"access-log-format", true, staticDefault("")},
|
||||
{"access-log-path", true, func(appName string) string {
|
||||
return fmt.Sprintf("%s/%s-access.log", openrestyLogRoot, appName)
|
||||
}},
|
||||
{"bind-address-ipv4", true, staticDefault("")},
|
||||
{"bind-address-ipv6", true, staticDefault("::")},
|
||||
{"client-body-timeout", true, staticDefault("60s")},
|
||||
{"client-header-timeout", true, staticDefault("60s")},
|
||||
{"client-max-body-size", true, staticDefault("1m")},
|
||||
{"error-log-path", true, func(appName string) string {
|
||||
return fmt.Sprintf("%s/%s-error.log", openrestyLogRoot, appName)
|
||||
}},
|
||||
{"hsts-include-subdomains", true, staticDefault("true")},
|
||||
{"hsts-max-age", true, staticDefault("15724800")},
|
||||
{"hsts-preload", true, staticDefault("false")},
|
||||
{"image", false, func(string) string { return dockerfileFromImage("openresty-vhosts") }},
|
||||
{"keepalive-timeout", true, staticDefault("75s")},
|
||||
{"letsencrypt-email", false, staticDefault("")},
|
||||
{"letsencrypt-server", false, staticDefault("https://acme-v02.api.letsencrypt.org/directory")},
|
||||
{"lingering-timeout", true, staticDefault("5s")},
|
||||
{"log-level", false, staticDefault("ERROR")},
|
||||
{"proxy-buffer-size", true, staticDefault(fmt.Sprintf("%dk", pageSize))},
|
||||
{"proxy-buffering", true, staticDefault("on")},
|
||||
{"proxy-buffers", true, staticDefault(fmt.Sprintf("8 %dk", pageSize))},
|
||||
{"proxy-busy-buffers-size", true, staticDefault(fmt.Sprintf("%dk", pageSize*2))},
|
||||
{"proxy-connect-timeout", true, staticDefault("60s")},
|
||||
{"proxy-read-timeout", true, staticDefault("60s")},
|
||||
{"proxy-send-timeout", true, staticDefault("60s")},
|
||||
{"send-timeout", true, staticDefault("60s")},
|
||||
{"underscore-in-headers", true, staticDefault("off")},
|
||||
{"x-forwarded-for-value", true, staticDefault("$remote_addr")},
|
||||
{"x-forwarded-port-value", true, staticDefault("$server_port")},
|
||||
{"x-forwarded-proto-value", true, staticDefault("$scheme")},
|
||||
{"x-forwarded-ssl", true, staticDefault("")},
|
||||
}
|
||||
}
|
||||
|
||||
// ReportSingleApp is an internal function that displays the openresty report for one or more apps
|
||||
func ReportSingleApp(appName string, format string, infoFlag string) error {
|
||||
if appName != "--global" {
|
||||
if err := common.VerifyAppName(appName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
isGlobal := appName == "--global"
|
||||
|
||||
flags := map[string]common.ReportFunc{}
|
||||
for _, p := range openrestyProps() {
|
||||
prop := p.name
|
||||
hasApp := p.hasApp
|
||||
computedDefault := p.computedDefault
|
||||
if hasApp && !isGlobal {
|
||||
flags["--openresty-"+prop] = func(app string) string {
|
||||
return common.PropertyGet("openresty", app, prop)
|
||||
}
|
||||
}
|
||||
flags["--openresty-global-"+prop] = func(app string) string {
|
||||
return common.PropertyGet("openresty", "--global", prop)
|
||||
}
|
||||
flags["--openresty-computed-"+prop] = func(app string) string {
|
||||
value := ""
|
||||
if hasApp && app != "--global" {
|
||||
value = common.PropertyGet("openresty", app, prop)
|
||||
}
|
||||
if value == "" {
|
||||
value = common.PropertyGet("openresty", "--global", prop)
|
||||
}
|
||||
if value == "" {
|
||||
value = computedDefault(app)
|
||||
}
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
flags["--openresty-global-allowed-letsencrypt-domains-func-base64"] = func(app string) string {
|
||||
return common.PropertyGet("openresty", "--global", "allowed-letsencrypt-domains-func-base64")
|
||||
}
|
||||
flags["--openresty-computed-allowed-letsencrypt-domains-func-base64"] = func(app string) string {
|
||||
value := common.PropertyGetDefault("openresty", "--global", "allowed-letsencrypt-domains-func-base64", "return true")
|
||||
return base64.StdEncoding.EncodeToString([]byte(value))
|
||||
}
|
||||
|
||||
if !isGlobal {
|
||||
flags["--openresty-hsts"] = func(app string) string {
|
||||
return common.PropertyGet("openresty", app, "hsts")
|
||||
}
|
||||
}
|
||||
flags["--openresty-global-hsts"] = func(app string) string {
|
||||
return common.PropertyGet("openresty", "--global", "hsts")
|
||||
}
|
||||
flags["--openresty-computed-hsts"] = openrestyHstsIsEnabled
|
||||
|
||||
flagKeys := []string{}
|
||||
for flagKey := range flags {
|
||||
flagKeys = append(flagKeys, flagKey)
|
||||
}
|
||||
|
||||
infoFlags := common.CollectReport(appName, infoFlag, flags)
|
||||
return common.ReportSingleApp(common.ReportSingleAppInput{
|
||||
ReportType: "openresty",
|
||||
AppName: appName,
|
||||
InfoFlag: infoFlag,
|
||||
InfoFlags: infoFlags,
|
||||
InfoFlagKeys: flagKeys,
|
||||
Format: format,
|
||||
TrimPrefix: true,
|
||||
UppercaseFirstCharacter: true,
|
||||
EmitLegacyPrefix: false,
|
||||
})
|
||||
}
|
||||
|
||||
func openrestyHstsIsEnabled(appName string) string {
|
||||
value := common.PropertyGet("openresty", appName, "hsts")
|
||||
if value == "" {
|
||||
value = common.PropertyGetDefault("openresty", "--global", "hsts", "true")
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// dockerfileFromImage returns the image referenced by the FROM line of the named
|
||||
// plugin's Dockerfile, or an empty string when it cannot be read
|
||||
func dockerfileFromImage(pluginName string) string {
|
||||
pluginPath := os.Getenv("PLUGIN_AVAILABLE_PATH")
|
||||
data, err := os.ReadFile(filepath.Join(pluginPath, pluginName, "Dockerfile"))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
if strings.Contains(line, "FROM") {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) >= 2 {
|
||||
return fields[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
40
plugins/openresty-vhosts/src/subcommands/subcommands.go
Normal file
40
plugins/openresty-vhosts/src/subcommands/subcommands.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
openrestyvhosts "github.com/dokku/dokku/plugins/openresty-vhosts"
|
||||
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// main entrypoint to all subcommands
|
||||
func main() {
|
||||
parts := strings.Split(os.Args[0], "/")
|
||||
subcommand := parts[len(parts)-1]
|
||||
|
||||
var err error
|
||||
switch subcommand {
|
||||
case "report":
|
||||
args := flag.NewFlagSet("openresty-vhosts:report", flag.ExitOnError)
|
||||
format := args.String("format", "stdout", "format: [ stdout | json ]")
|
||||
reportArgs, flagErr := common.ParseReportArgs("openresty-vhosts", os.Args[2:])
|
||||
if flagErr == nil {
|
||||
args.Parse(reportArgs.OSArgs)
|
||||
appName := args.Arg(0)
|
||||
if reportArgs.IsGlobal {
|
||||
appName = "--global"
|
||||
}
|
||||
err = openrestyvhosts.CommandReport(appName, *format, reportArgs.InfoFlag)
|
||||
}
|
||||
default:
|
||||
err = fmt.Errorf("Invalid plugin subcommand call: %s", subcommand)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
common.LogFailWithError(err)
|
||||
}
|
||||
}
|
||||
31
plugins/openresty-vhosts/src/triggers/triggers.go
Normal file
31
plugins/openresty-vhosts/src/triggers/triggers.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
openrestyvhosts "github.com/dokku/dokku/plugins/openresty-vhosts"
|
||||
)
|
||||
|
||||
// main entrypoint to all triggers
|
||||
func main() {
|
||||
parts := strings.Split(os.Args[0], "/")
|
||||
trigger := parts[len(parts)-1]
|
||||
flag.Parse()
|
||||
|
||||
var err error
|
||||
switch trigger {
|
||||
case "report":
|
||||
appName := flag.Arg(0)
|
||||
err = openrestyvhosts.ReportSingleApp(appName, "", "")
|
||||
default:
|
||||
err = fmt.Errorf("Invalid plugin trigger call: %s", trigger)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
common.LogFailWithError(err)
|
||||
}
|
||||
}
|
||||
29
plugins/openresty-vhosts/subcommands.go
Normal file
29
plugins/openresty-vhosts/subcommands.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package openrestyvhosts
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
// CommandReport displays a openresty-vhosts report for one or more apps
|
||||
func CommandReport(appName string, format string, infoFlag string) error {
|
||||
if len(appName) == 0 {
|
||||
apps, err := common.DokkuApps()
|
||||
if err != nil {
|
||||
if errors.Is(err, common.NoAppsExist) {
|
||||
common.LogWarn(err.Error())
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
for _, appName := range apps {
|
||||
if err := ReportSingleApp(appName, format, infoFlag); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return ReportSingleApp(appName, format, infoFlag)
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$PLUGIN_AVAILABLE_PATH/openresty-vhosts/command-functions"
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
cmd-openresty-report "$@"
|
||||
4
plugins/traefik-vhosts/.gitignore
vendored
Normal file
4
plugins/traefik-vhosts/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/report
|
||||
/report-subcommand
|
||||
/triggers
|
||||
/subcommands/report
|
||||
13
plugins/traefik-vhosts/Makefile
Normal file
13
plugins/traefik-vhosts/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
GOARCH ?= amd64
|
||||
TRIGGERS = triggers/report
|
||||
BUILD = report-subcommand triggers
|
||||
PLUGIN_NAME = traefik-vhosts
|
||||
|
||||
clean-report-subcommand:
|
||||
rm -rf report-subcommand
|
||||
|
||||
report-subcommand: clean-report-subcommand src/subcommands/subcommands.go
|
||||
GOARCH=$(GOARCH) go build -mod=readonly -ldflags="-s -w" $(GO_ARGS) -o report-subcommand src/subcommands/subcommands.go
|
||||
ln -sf ../report-subcommand subcommands/report
|
||||
|
||||
include ../../common.mk
|
||||
125
plugins/traefik-vhosts/command-functions
Executable file → Normal file
125
plugins/traefik-vhosts/command-functions
Executable file → Normal file
@@ -30,131 +30,6 @@ cmd-traefik-labels-show() {
|
||||
cmd-proxy-labels-show "proxy:labels:show" "traefik" "$@"
|
||||
}
|
||||
|
||||
cmd-traefik-report() {
|
||||
declare desc="displays a traefik report for one or more apps"
|
||||
declare cmd="traefik:report"
|
||||
[[ "$1" == "$cmd" ]] && shift 1
|
||||
fn-report-parse-args "$@"
|
||||
set -- "${REPORT_ARGS[@]}"
|
||||
declare APP="${1:-}" INFO_FLAG="${2:-}"
|
||||
|
||||
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
|
||||
INFO_FLAG="$APP"
|
||||
APP=""
|
||||
fi
|
||||
|
||||
if [[ "$REPORT_IS_GLOBAL" == "true" ]]; then
|
||||
APP="--global"
|
||||
fi
|
||||
|
||||
if [[ -z "$APP" ]] && [[ -z "$INFO_FLAG" ]]; then
|
||||
INFO_FLAG="true"
|
||||
fi
|
||||
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
cmd-traefik-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
elif [[ -z "$APP" ]]; then
|
||||
for app in $(dokku_apps); do
|
||||
cmd-traefik-report-single "$app" "$INFO_FLAG" "$REPORT_FORMAT" | tee || true
|
||||
done
|
||||
else
|
||||
cmd-traefik-report-single "$APP" "$INFO_FLAG" "$REPORT_FORMAT"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd-traefik-report-single() {
|
||||
declare APP="$1" INFO_FLAG="$2" FORMAT="${3:-stdout}"
|
||||
if [[ "$INFO_FLAG" == "true" ]]; then
|
||||
INFO_FLAG=""
|
||||
fi
|
||||
if [[ "$APP" != "--global" ]]; then
|
||||
verify_app_name "$APP"
|
||||
fi
|
||||
local flag_map=(
|
||||
"--traefik-computed-api-enabled: $(fn-traefik-computed-api-enabled)"
|
||||
"--traefik-computed-api-entry-point: $(fn-traefik-computed-api-entry-point)"
|
||||
"--traefik-computed-api-entry-point-address: $(fn-traefik-computed-api-entry-point-address)"
|
||||
"--traefik-computed-api-vhost: $(fn-traefik-computed-api-vhost)"
|
||||
"--traefik-computed-basic-auth-password: $(fn-traefik-computed-basic-auth-password)"
|
||||
"--traefik-computed-basic-auth-username: $(fn-traefik-computed-basic-auth-username)"
|
||||
"--traefik-computed-challenge-mode: $(fn-traefik-computed-challenge-mode)"
|
||||
"--traefik-computed-dashboard-enabled: $(fn-traefik-computed-dashboard-enabled)"
|
||||
"--traefik-computed-dns-provider: $(fn-traefik-computed-dns-provider)"
|
||||
"--traefik-computed-http-entry-point: $(fn-traefik-computed-http-entry-point)"
|
||||
"--traefik-computed-https-entry-point: $(fn-traefik-computed-https-entry-point)"
|
||||
"--traefik-computed-image: $(fn-traefik-computed-image)"
|
||||
"--traefik-computed-letsencrypt-email: $(fn-traefik-computed-letsencrypt-email)"
|
||||
"--traefik-computed-letsencrypt-server: $(fn-traefik-computed-letsencrypt-server)"
|
||||
"--traefik-computed-log-level: $(fn-traefik-computed-log-level)"
|
||||
"--traefik-global-api-enabled: $(fn-traefik-global-api-enabled)"
|
||||
"--traefik-global-api-entry-point: $(fn-traefik-global-api-entry-point)"
|
||||
"--traefik-global-api-entry-point-address: $(fn-traefik-global-api-entry-point-address)"
|
||||
"--traefik-global-api-vhost: $(fn-traefik-global-api-vhost)"
|
||||
"--traefik-global-basic-auth-password: $(fn-traefik-global-basic-auth-password)"
|
||||
"--traefik-global-basic-auth-username: $(fn-traefik-global-basic-auth-username)"
|
||||
"--traefik-global-challenge-mode: $(fn-traefik-global-challenge-mode)"
|
||||
"--traefik-global-dashboard-enabled: $(fn-traefik-global-dashboard-enabled)"
|
||||
"--traefik-global-dns-provider: $(fn-traefik-global-dns-provider)"
|
||||
"--traefik-global-http-entry-point: $(fn-traefik-global-http-entry-point)"
|
||||
"--traefik-global-https-entry-point: $(fn-traefik-global-https-entry-point)"
|
||||
"--traefik-global-image: $(fn-traefik-global-image)"
|
||||
"--traefik-global-letsencrypt-email: $(fn-traefik-global-letsencrypt-email)"
|
||||
"--traefik-global-letsencrypt-server: $(fn-traefik-global-letsencrypt-server)"
|
||||
"--traefik-global-log-level: $(fn-traefik-global-log-level)"
|
||||
)
|
||||
|
||||
local dns_provider_env_vars
|
||||
dns_provider_env_vars="$(fn-traefik-dns-provider-env-vars)"
|
||||
if [[ -n "$dns_provider_env_vars" ]]; then
|
||||
while IFS= read -r line; do
|
||||
local key value
|
||||
key="$(echo "$line" | cut -d' ' -f1)"
|
||||
value="$(echo "$line" | cut -d' ' -f2-)"
|
||||
if [[ -n "$key" ]]; then
|
||||
if [[ "$FORMAT" == "json" ]] || [[ "$INFO_FLAG" == "--traefik-${key}" ]]; then
|
||||
flag_map+=("--traefik-${key}: ${value}")
|
||||
else
|
||||
flag_map+=("--traefik-${key}: *******")
|
||||
fi
|
||||
fi
|
||||
done <<<"$dns_provider_env_vars"
|
||||
fi
|
||||
|
||||
fn-report-validate-format "$FORMAT" "$INFO_FLAG"
|
||||
|
||||
if [[ "$FORMAT" == "json" ]]; then
|
||||
fn-report-emit-json flag_map "traefik"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "$INFO_FLAG" ]]; then
|
||||
if [[ "$APP" == "--global" ]]; then
|
||||
dokku_log_info2_quiet "global traefik information"
|
||||
else
|
||||
dokku_log_info2_quiet "${APP} traefik information"
|
||||
fi
|
||||
for flag in "${flag_map[@]}"; do
|
||||
key="$(echo "${flag#--}" | cut -f1 -d' ' | tr - ' ')"
|
||||
dokku_log_verbose "$(printf "%-30s %-25s" "${key^}" "${flag#*: }")"
|
||||
done
|
||||
else
|
||||
local match=false
|
||||
for flag in "${flag_map[@]}"; do
|
||||
valid_flags="${valid_flags} $(echo "$flag" | cut -d':' -f1)"
|
||||
if [[ "$flag" == "${INFO_FLAG}:"* ]]; then
|
||||
value=${flag#*: }
|
||||
size="${#value}"
|
||||
if [[ "$size" -ne 0 ]]; then
|
||||
echo "$value" && match=true
|
||||
else
|
||||
match=true
|
||||
fi
|
||||
fi
|
||||
done
|
||||
[[ "$match" == "true" ]] || dokku_log_fail "Invalid flag passed, valid flags:${valid_flags}"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd-traefik-logs() {
|
||||
declare desc="display traefik logs from command line"
|
||||
declare cmd="traefik:logs"
|
||||
|
||||
29
plugins/traefik-vhosts/go.mod
Normal file
29
plugins/traefik-vhosts/go.mod
Normal file
@@ -0,0 +1,29 @@
|
||||
module github.com/dokku/dokku/plugins/traefik-vhosts
|
||||
|
||||
go 1.26.2
|
||||
|
||||
require (
|
||||
github.com/dokku/dokku/plugins/common v0.0.0-00010101000000-000000000000
|
||||
github.com/spf13/pflag v1.0.10
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/fatih/color v1.19.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/melbahja/goph v1.5.1 // indirect
|
||||
github.com/otiai10/copy v1.14.1 // indirect
|
||||
github.com/otiai10/mint v1.6.3 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/sftp v1.13.10 // indirect
|
||||
github.com/ryanuber/columnize v2.1.2+incompatible // indirect
|
||||
golang.org/x/crypto v0.53.0 // indirect
|
||||
golang.org/x/sync v0.21.0 // indirect
|
||||
golang.org/x/sys v0.46.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/dokku/dokku/plugins/common => ../common
|
||||
55
plugins/traefik-vhosts/go.sum
Normal file
55
plugins/traefik-vhosts/go.sum
Normal file
@@ -0,0 +1,55 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w=
|
||||
github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/melbahja/goph v1.5.1 h1:gdZyjn5nM6FO6mAZrv7XqE2gArQbb+V6FdIyH3Ru3vA=
|
||||
github.com/melbahja/goph v1.5.1/go.mod h1:dDwo+44cmvfDLdiVpc6fJxexf5BA5yEDUeE5YgtuDO4=
|
||||
github.com/onsi/gomega v1.42.1 h1:iN1rCUX+44NZ1Dc97MPoeFYbFR0vh8zxoxMFwKdyZ6I=
|
||||
github.com/onsi/gomega v1.42.1/go.mod h1:REff/hsDsodHoKlWsP2mAPhu1+5/6hVYNf9rIEBpeSg=
|
||||
github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8=
|
||||
github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I=
|
||||
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=
|
||||
github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.10 h1:+5FbKNTe5Z9aspU88DPIKJ9z2KZoaGCu6Sr6kKR/5mU=
|
||||
github.com/pkg/sftp v1.13.10/go.mod h1:bJ1a7uDhrX/4OII+agvy28lzRvQrmIQuaHrcI1HbeGA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/ryanuber/columnize v2.1.2+incompatible h1:C89EOx/XBWwIXl8wm8OPJBd7kPF25UfsK2X7Ph/zCAk=
|
||||
github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
|
||||
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
|
||||
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
|
||||
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
|
||||
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
|
||||
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
|
||||
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
|
||||
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
|
||||
golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
|
||||
golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$PLUGIN_AVAILABLE_PATH/traefik-vhosts/command-functions"
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
cmd-traefik-report-single "$@"
|
||||
271
plugins/traefik-vhosts/report.go
Normal file
271
plugins/traefik-vhosts/report.go
Normal file
@@ -0,0 +1,271 @@
|
||||
package traefikvhosts
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
// ReportSingleApp is an internal function that displays the traefik report for one or more apps
|
||||
func ReportSingleApp(appName string, format string, infoFlag string) error {
|
||||
if appName != "--global" {
|
||||
if err := common.VerifyAppName(appName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
flags := map[string]common.ReportFunc{
|
||||
"--traefik-computed-api-enabled": reportComputedAPIEnabled,
|
||||
"--traefik-computed-api-entry-point": reportComputedAPIEntryPoint,
|
||||
"--traefik-computed-api-entry-point-address": reportComputedAPIEntryPointAddress,
|
||||
"--traefik-computed-api-vhost": reportComputedAPIVhost,
|
||||
"--traefik-computed-basic-auth-password": reportComputedBasicAuthPassword,
|
||||
"--traefik-computed-basic-auth-username": reportComputedBasicAuthUsername,
|
||||
"--traefik-computed-challenge-mode": reportComputedChallengeMode,
|
||||
"--traefik-computed-dashboard-enabled": reportComputedDashboardEnabled,
|
||||
"--traefik-computed-dns-provider": reportComputedDNSProvider,
|
||||
"--traefik-computed-http-entry-point": reportComputedHTTPEntryPoint,
|
||||
"--traefik-computed-https-entry-point": reportComputedHTTPSEntryPoint,
|
||||
"--traefik-computed-image": reportComputedImage,
|
||||
"--traefik-computed-letsencrypt-email": reportComputedLetsencryptEmail,
|
||||
"--traefik-computed-letsencrypt-server": reportComputedLetsencryptServer,
|
||||
"--traefik-computed-log-level": reportComputedLogLevel,
|
||||
"--traefik-global-api-enabled": reportGlobalAPIEnabled,
|
||||
"--traefik-global-api-entry-point": reportGlobalAPIEntryPoint,
|
||||
"--traefik-global-api-entry-point-address": reportGlobalAPIEntryPointAddress,
|
||||
"--traefik-global-api-vhost": reportGlobalAPIVhost,
|
||||
"--traefik-global-basic-auth-password": reportGlobalBasicAuthPassword,
|
||||
"--traefik-global-basic-auth-username": reportGlobalBasicAuthUsername,
|
||||
"--traefik-global-challenge-mode": reportGlobalChallengeMode,
|
||||
"--traefik-global-dashboard-enabled": reportGlobalDashboardEnabled,
|
||||
"--traefik-global-dns-provider": reportGlobalDNSProvider,
|
||||
"--traefik-global-http-entry-point": reportGlobalHTTPEntryPoint,
|
||||
"--traefik-global-https-entry-point": reportGlobalHTTPSEntryPoint,
|
||||
"--traefik-global-image": reportGlobalImage,
|
||||
"--traefik-global-letsencrypt-email": reportGlobalLetsencryptEmail,
|
||||
"--traefik-global-letsencrypt-server": reportGlobalLetsencryptServer,
|
||||
"--traefik-global-log-level": reportGlobalLogLevel,
|
||||
}
|
||||
|
||||
// dns-provider-* env vars are dynamic; their values are masked in the default
|
||||
// stdout report, but shown for --format json or when queried explicitly by name
|
||||
dnsProviderVars, err := common.PropertyGetAllByPrefix("traefik", "--global", "dns-provider-")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for key, value := range dnsProviderVars {
|
||||
flagName := "--traefik-" + key
|
||||
realValue := value
|
||||
if format == "json" || infoFlag == flagName {
|
||||
flags[flagName] = func(string) string { return realValue }
|
||||
} else {
|
||||
flags[flagName] = func(string) string { return "*******" }
|
||||
}
|
||||
}
|
||||
|
||||
flagKeys := []string{}
|
||||
for flagKey := range flags {
|
||||
flagKeys = append(flagKeys, flagKey)
|
||||
}
|
||||
|
||||
infoFlags := common.CollectReport(appName, infoFlag, flags)
|
||||
return common.ReportSingleApp(common.ReportSingleAppInput{
|
||||
ReportType: "traefik",
|
||||
AppName: appName,
|
||||
InfoFlag: infoFlag,
|
||||
InfoFlags: infoFlags,
|
||||
InfoFlagKeys: flagKeys,
|
||||
Format: format,
|
||||
TrimPrefix: true,
|
||||
UppercaseFirstCharacter: true,
|
||||
EmitLegacyPrefix: false,
|
||||
})
|
||||
}
|
||||
|
||||
func reportGlobalAPIEnabled(appName string) string {
|
||||
return common.PropertyGet("traefik", "--global", "api-enabled")
|
||||
}
|
||||
|
||||
func reportComputedAPIEnabled(appName string) string {
|
||||
value := reportGlobalAPIEnabled(appName)
|
||||
if value == "" {
|
||||
value = "false"
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func reportGlobalAPIEntryPoint(appName string) string {
|
||||
return common.PropertyGet("traefik", "--global", "api-entry-point")
|
||||
}
|
||||
|
||||
func reportComputedAPIEntryPoint(appName string) string {
|
||||
return reportGlobalAPIEntryPoint(appName)
|
||||
}
|
||||
|
||||
func reportGlobalAPIEntryPointAddress(appName string) string {
|
||||
return common.PropertyGet("traefik", "--global", "api-entry-point-address")
|
||||
}
|
||||
|
||||
func reportComputedAPIEntryPointAddress(appName string) string {
|
||||
return reportGlobalAPIEntryPointAddress(appName)
|
||||
}
|
||||
|
||||
func reportGlobalAPIVhost(appName string) string {
|
||||
return common.PropertyGet("traefik", "--global", "api-vhost")
|
||||
}
|
||||
|
||||
func reportComputedAPIVhost(appName string) string {
|
||||
value := reportGlobalAPIVhost(appName)
|
||||
if value == "" {
|
||||
value = "traefik.dokku.me"
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func reportGlobalBasicAuthPassword(appName string) string {
|
||||
return common.PropertyGet("traefik", "--global", "basic-auth-password")
|
||||
}
|
||||
|
||||
func reportComputedBasicAuthPassword(appName string) string {
|
||||
return reportGlobalBasicAuthPassword(appName)
|
||||
}
|
||||
|
||||
func reportGlobalBasicAuthUsername(appName string) string {
|
||||
return common.PropertyGet("traefik", "--global", "basic-auth-username")
|
||||
}
|
||||
|
||||
func reportComputedBasicAuthUsername(appName string) string {
|
||||
return reportGlobalBasicAuthUsername(appName)
|
||||
}
|
||||
|
||||
func reportGlobalChallengeMode(appName string) string {
|
||||
return common.PropertyGet("traefik", "--global", "challenge-mode")
|
||||
}
|
||||
|
||||
func reportComputedChallengeMode(appName string) string {
|
||||
value := reportGlobalChallengeMode(appName)
|
||||
if value == "" {
|
||||
value = "tls"
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func reportGlobalDashboardEnabled(appName string) string {
|
||||
return common.PropertyGet("traefik", "--global", "dashboard-enabled")
|
||||
}
|
||||
|
||||
func reportComputedDashboardEnabled(appName string) string {
|
||||
value := reportGlobalDashboardEnabled(appName)
|
||||
if value == "" {
|
||||
value = "false"
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func reportGlobalDNSProvider(appName string) string {
|
||||
return common.PropertyGet("traefik", "--global", "dns-provider")
|
||||
}
|
||||
|
||||
func reportComputedDNSProvider(appName string) string {
|
||||
return reportGlobalDNSProvider(appName)
|
||||
}
|
||||
|
||||
func reportGlobalHTTPEntryPoint(appName string) string {
|
||||
return common.PropertyGet("traefik", "--global", "http-entry-point")
|
||||
}
|
||||
|
||||
func reportComputedHTTPEntryPoint(appName string) string {
|
||||
value := reportGlobalHTTPEntryPoint(appName)
|
||||
if value == "" {
|
||||
value = "http"
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func reportGlobalHTTPSEntryPoint(appName string) string {
|
||||
return common.PropertyGet("traefik", "--global", "https-entry-point")
|
||||
}
|
||||
|
||||
func reportComputedHTTPSEntryPoint(appName string) string {
|
||||
value := reportGlobalHTTPSEntryPoint(appName)
|
||||
if value == "" {
|
||||
value = "https"
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func reportGlobalImage(appName string) string {
|
||||
return common.PropertyGet("traefik", "--global", "image")
|
||||
}
|
||||
|
||||
func reportComputedImage(appName string) string {
|
||||
value := reportGlobalImage(appName)
|
||||
if value == "" {
|
||||
value = dockerfileFromImage("traefik-vhosts")
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func reportGlobalLetsencryptEmail(appName string) string {
|
||||
return common.PropertyGet("traefik", "--global", "letsencrypt-email")
|
||||
}
|
||||
|
||||
func reportComputedLetsencryptEmail(appName string) string {
|
||||
return reportGlobalLetsencryptEmail(appName)
|
||||
}
|
||||
|
||||
func reportGlobalLetsencryptServer(appName string) string {
|
||||
return common.PropertyGet("traefik", "--global", "letsencrypt-server")
|
||||
}
|
||||
|
||||
func reportComputedLetsencryptServer(appName string) string {
|
||||
value := reportGlobalLetsencryptServer(appName)
|
||||
if value == "" {
|
||||
value = "https://acme-v02.api.letsencrypt.org/directory"
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func reportGlobalLogLevel(appName string) string {
|
||||
return common.PropertyGet("traefik", "--global", "log-level")
|
||||
}
|
||||
|
||||
func reportComputedLogLevel(appName string) string {
|
||||
value := reportGlobalLogLevel(appName)
|
||||
if value == "" {
|
||||
value = "ERROR"
|
||||
}
|
||||
|
||||
return strings.ToUpper(value)
|
||||
}
|
||||
|
||||
// dockerfileFromImage returns the image referenced by the FROM line of the named
|
||||
// plugin's Dockerfile, or an empty string when it cannot be read
|
||||
func dockerfileFromImage(pluginName string) string {
|
||||
pluginPath := os.Getenv("PLUGIN_AVAILABLE_PATH")
|
||||
data, err := os.ReadFile(filepath.Join(pluginPath, pluginName, "Dockerfile"))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
if strings.Contains(line, "FROM") {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) >= 2 {
|
||||
return fields[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
40
plugins/traefik-vhosts/src/subcommands/subcommands.go
Normal file
40
plugins/traefik-vhosts/src/subcommands/subcommands.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
traefikvhosts "github.com/dokku/dokku/plugins/traefik-vhosts"
|
||||
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// main entrypoint to all subcommands
|
||||
func main() {
|
||||
parts := strings.Split(os.Args[0], "/")
|
||||
subcommand := parts[len(parts)-1]
|
||||
|
||||
var err error
|
||||
switch subcommand {
|
||||
case "report":
|
||||
args := flag.NewFlagSet("traefik-vhosts:report", flag.ExitOnError)
|
||||
format := args.String("format", "stdout", "format: [ stdout | json ]")
|
||||
reportArgs, flagErr := common.ParseReportArgs("traefik-vhosts", os.Args[2:])
|
||||
if flagErr == nil {
|
||||
args.Parse(reportArgs.OSArgs)
|
||||
appName := args.Arg(0)
|
||||
if reportArgs.IsGlobal {
|
||||
appName = "--global"
|
||||
}
|
||||
err = traefikvhosts.CommandReport(appName, *format, reportArgs.InfoFlag)
|
||||
}
|
||||
default:
|
||||
err = fmt.Errorf("Invalid plugin subcommand call: %s", subcommand)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
common.LogFailWithError(err)
|
||||
}
|
||||
}
|
||||
31
plugins/traefik-vhosts/src/triggers/triggers.go
Normal file
31
plugins/traefik-vhosts/src/triggers/triggers.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
traefikvhosts "github.com/dokku/dokku/plugins/traefik-vhosts"
|
||||
)
|
||||
|
||||
// main entrypoint to all triggers
|
||||
func main() {
|
||||
parts := strings.Split(os.Args[0], "/")
|
||||
trigger := parts[len(parts)-1]
|
||||
flag.Parse()
|
||||
|
||||
var err error
|
||||
switch trigger {
|
||||
case "report":
|
||||
appName := flag.Arg(0)
|
||||
err = traefikvhosts.ReportSingleApp(appName, "", "")
|
||||
default:
|
||||
err = fmt.Errorf("Invalid plugin trigger call: %s", trigger)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
common.LogFailWithError(err)
|
||||
}
|
||||
}
|
||||
29
plugins/traefik-vhosts/subcommands.go
Normal file
29
plugins/traefik-vhosts/subcommands.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package traefikvhosts
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
// CommandReport displays a traefik-vhosts report for one or more apps
|
||||
func CommandReport(appName string, format string, infoFlag string) error {
|
||||
if len(appName) == 0 {
|
||||
apps, err := common.DokkuApps()
|
||||
if err != nil {
|
||||
if errors.Is(err, common.NoAppsExist) {
|
||||
common.LogWarn(err.Error())
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
for _, appName := range apps {
|
||||
if err := ReportSingleApp(appName, format, infoFlag); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return ReportSingleApp(appName, format, infoFlag)
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$PLUGIN_AVAILABLE_PATH/traefik-vhosts/command-functions"
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
cmd-traefik-report "$@"
|
||||
84
tests/unit/caddy-vhosts.bats
Normal file
84
tests/unit/caddy-vhosts.bats
Normal file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
setup() {
|
||||
create_app
|
||||
}
|
||||
|
||||
teardown() {
|
||||
destroy_app
|
||||
dokku caddy:set --global log-level >/dev/null 2>&1 || true
|
||||
dokku caddy:set --global tls-internal >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
@test "(caddy:report) info-flag works before deploy" {
|
||||
run /bin/bash -c "dokku caddy:report $TEST_APP --caddy-computed-tls-internal"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "false"
|
||||
|
||||
run /bin/bash -c "dokku caddy:report $TEST_APP --caddy-invalid-flag"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_failure
|
||||
assert_output_contains "Invalid flag passed"
|
||||
}
|
||||
|
||||
@test "(caddy:report) --format json" {
|
||||
run /bin/bash -c "dokku caddy:set --global log-level"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku caddy:report --global --format json | jq -e ."
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku caddy:report --global --format json | jq -r '.\"computed-log-level\"'"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "ERROR"
|
||||
|
||||
run /bin/bash -c "dokku caddy:report --global"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output_contains "global caddy information"
|
||||
}
|
||||
|
||||
@test "(caddy:report) tls-internal raw global computed" {
|
||||
run /bin/bash -c "dokku caddy:set --global tls-internal"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku caddy:report $TEST_APP --caddy-tls-internal"
|
||||
assert_success
|
||||
assert_output ""
|
||||
|
||||
run /bin/bash -c "dokku caddy:report $TEST_APP --caddy-computed-tls-internal"
|
||||
assert_success
|
||||
assert_output "false"
|
||||
|
||||
run /bin/bash -c "dokku caddy:set --global tls-internal true"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku caddy:report $TEST_APP --caddy-global-tls-internal"
|
||||
assert_success
|
||||
assert_output "true"
|
||||
|
||||
run /bin/bash -c "dokku caddy:report $TEST_APP --caddy-computed-tls-internal"
|
||||
assert_success
|
||||
assert_output "true"
|
||||
|
||||
run /bin/bash -c "dokku caddy:set $TEST_APP tls-internal false"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku caddy:report $TEST_APP --caddy-tls-internal"
|
||||
assert_success
|
||||
assert_output "false"
|
||||
|
||||
run /bin/bash -c "dokku caddy:report $TEST_APP --caddy-computed-tls-internal"
|
||||
assert_success
|
||||
assert_output "false"
|
||||
}
|
||||
76
tests/unit/haproxy-vhosts.bats
Normal file
76
tests/unit/haproxy-vhosts.bats
Normal file
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
setup() {
|
||||
create_app
|
||||
}
|
||||
|
||||
teardown() {
|
||||
destroy_app
|
||||
dokku haproxy:set --global log-level >/dev/null 2>&1 || true
|
||||
dokku haproxy:set --global refresh-conf >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
@test "(haproxy:report) info-flag works before deploy" {
|
||||
run /bin/bash -c "dokku haproxy:set --global refresh-conf"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku haproxy:report $TEST_APP --haproxy-computed-refresh-conf"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "10"
|
||||
|
||||
run /bin/bash -c "dokku haproxy:report $TEST_APP --haproxy-invalid-flag"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_failure
|
||||
assert_output_contains "Invalid flag passed"
|
||||
}
|
||||
|
||||
@test "(haproxy:report) --format json" {
|
||||
run /bin/bash -c "dokku haproxy:set --global log-level"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku haproxy:report --global --format json | jq -e ."
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku haproxy:report --global --format json | jq -r '.\"computed-log-level\"'"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "ERROR"
|
||||
|
||||
run /bin/bash -c "dokku haproxy:report --global"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output_contains "global haproxy information"
|
||||
}
|
||||
|
||||
@test "(haproxy:report) refresh-conf global computed" {
|
||||
run /bin/bash -c "dokku haproxy:set --global refresh-conf"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku haproxy:report --global --haproxy-global-refresh-conf"
|
||||
assert_success
|
||||
assert_output ""
|
||||
|
||||
run /bin/bash -c "dokku haproxy:report --global --haproxy-computed-refresh-conf"
|
||||
assert_success
|
||||
assert_output "10"
|
||||
|
||||
run /bin/bash -c "dokku haproxy:set --global refresh-conf 30"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku haproxy:report --global --haproxy-global-refresh-conf"
|
||||
assert_success
|
||||
assert_output "30"
|
||||
|
||||
run /bin/bash -c "dokku haproxy:report --global --haproxy-computed-refresh-conf"
|
||||
assert_success
|
||||
assert_output "30"
|
||||
}
|
||||
84
tests/unit/openresty-vhosts.bats
Normal file
84
tests/unit/openresty-vhosts.bats
Normal file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
setup() {
|
||||
create_app
|
||||
}
|
||||
|
||||
teardown() {
|
||||
destroy_app
|
||||
dokku openresty:set --global log-level >/dev/null 2>&1 || true
|
||||
dokku openresty:set --global proxy-buffer-size >/dev/null 2>&1 || true
|
||||
dokku openresty:set --global client-max-body-size >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
@test "(openresty:report) info-flag works before deploy" {
|
||||
run /bin/bash -c "dokku openresty:set --global log-level"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku openresty:report $TEST_APP --openresty-computed-log-level"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "ERROR"
|
||||
|
||||
run /bin/bash -c "dokku openresty:report $TEST_APP --openresty-invalid-flag"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_failure
|
||||
assert_output_contains "Invalid flag passed"
|
||||
}
|
||||
|
||||
@test "(openresty:report) --format json" {
|
||||
run /bin/bash -c "dokku openresty:set --global proxy-buffer-size"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku openresty:report --global --format json | jq -e ."
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku openresty:report --global --format json | jq -r '.\"computed-proxy-buffer-size\"'"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "4k"
|
||||
|
||||
run /bin/bash -c "dokku openresty:report --global"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output_contains "global openresty information"
|
||||
}
|
||||
|
||||
@test "(openresty:report) client-max-body-size raw global computed" {
|
||||
run /bin/bash -c "dokku openresty:set --global client-max-body-size"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku openresty:report $TEST_APP --openresty-client-max-body-size"
|
||||
assert_success
|
||||
assert_output ""
|
||||
|
||||
run /bin/bash -c "dokku openresty:report $TEST_APP --openresty-computed-client-max-body-size"
|
||||
assert_success
|
||||
assert_output "1m"
|
||||
|
||||
run /bin/bash -c "dokku openresty:set --global client-max-body-size 2m"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku openresty:report $TEST_APP --openresty-computed-client-max-body-size"
|
||||
assert_success
|
||||
assert_output "2m"
|
||||
|
||||
run /bin/bash -c "dokku openresty:set $TEST_APP client-max-body-size 5m"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku openresty:report $TEST_APP --openresty-client-max-body-size"
|
||||
assert_success
|
||||
assert_output "5m"
|
||||
|
||||
run /bin/bash -c "dokku openresty:report $TEST_APP --openresty-computed-client-max-body-size"
|
||||
assert_success
|
||||
assert_output "5m"
|
||||
}
|
||||
72
tests/unit/traefik-vhosts.bats
Normal file
72
tests/unit/traefik-vhosts.bats
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
setup() {
|
||||
create_app
|
||||
}
|
||||
|
||||
teardown() {
|
||||
destroy_app
|
||||
dokku traefik:set --global challenge-mode >/dev/null 2>&1 || true
|
||||
dokku traefik:set --global dns-provider-test_key >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
@test "(traefik:report) info-flag works before deploy" {
|
||||
run /bin/bash -c "dokku traefik:set --global challenge-mode"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku traefik:report $TEST_APP --traefik-computed-challenge-mode"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "tls"
|
||||
|
||||
run /bin/bash -c "dokku traefik:report $TEST_APP --traefik-invalid-flag"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_failure
|
||||
assert_output_contains "Invalid flag passed"
|
||||
}
|
||||
|
||||
@test "(traefik:report) --format json" {
|
||||
run /bin/bash -c "dokku traefik:report --global --format json | jq -e ."
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku traefik:report --global --format json | jq -r '.\"computed-api-enabled\"'"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "false"
|
||||
|
||||
run /bin/bash -c "dokku traefik:report --global"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output_contains "global traefik information"
|
||||
}
|
||||
|
||||
@test "(traefik:report) dns-provider values are masked unless queried" {
|
||||
run /bin/bash -c "dokku traefik:set --global dns-provider-test_key secretvalue"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku traefik:report --global | grep test_key"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output_contains "*******"
|
||||
|
||||
run /bin/bash -c "dokku traefik:report --global --traefik-dns-provider-test_key"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "secretvalue"
|
||||
|
||||
run /bin/bash -c "dokku traefik:report --global --format json | jq -r '.\"dns-provider-test_key\"'"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "secretvalue"
|
||||
}
|
||||
Reference in New Issue
Block a user