feat: expose scheduler-k3s autoscaling-auth state for read-back

Align autoscaling-auth:report with annotations and labels reporting so export tools can recover configured trigger auth via flat JSON keys and info flags, while stdout stays secret-safe unless --include-metadata is used.

Closes #8800
This commit is contained in:
Jose Diaz-Gonzalez
2026-07-07 18:07:39 -04:00
parent 25b1356435
commit b2c4f61387
10 changed files with 605 additions and 37 deletions

View File

@@ -657,8 +657,8 @@ dokku scheduler-k3s:autoscaling-auth:report --global
```
```
====> $APP autoscaling-auth report
datadog: configured
====> node-js-app autoscaling-auth information
Datadog: configured
```
By default, the report will not display configured metadata - making it safe to include in Dokku report output. To include metadata and their values, add the `--include-metadata` flag:
@@ -668,13 +668,25 @@ dokku scheduler-k3s:autoscaling-auth:report node-js-app --include-metadata
```
```
====> node-js-app autoscaling-auth report
====> node-js-app autoscaling-auth information
Datadog: configured
Datadog apiKey: 1234567890
Datadog appKey: asdfghjkl
Datadog datadogSite: us5.datadoghq.com
```
JSON output emits flat keys of the form `{trigger}.{metadata_key}` and includes the actual metadata values so export tools can reconstruct the configured state:
```shell
dokku scheduler-k3s:autoscaling-auth:report node-js-app --format json
```
A single configured metadata key can also be queried with a flag of the form `--scheduler-k3s-autoscaling-auth.{trigger}.{metadata_key}`. The returned value is masked in the same way as stdout output; use `--format json` to read the actual value:
```shell
dokku scheduler-k3s:autoscaling-auth:report node-js-app --scheduler-k3s-autoscaling-auth.datadog.apiKey
```
### Integrating Kustomize
Dokku supports integration with [Kustomize](https://kustomize.io/) to further customize the generated helm charts for app deployments. For example, a `config/kustomize/kustomization.yaml` file with the following contents will override the scale for each process deployed to `3`:

View File

@@ -7,3 +7,4 @@
/post-*
/report
/core-*
/storage-*

View File

@@ -10,8 +10,9 @@ import (
)
const (
annotationsReportType = "scheduler-k3s-annotations"
labelsReportType = "scheduler-k3s-labels"
annotationsReportType = "scheduler-k3s-annotations"
labelsReportType = "scheduler-k3s-labels"
autoscalingAuthReportType = "scheduler-k3s-autoscaling-auth"
// reportProcessTypeGlobal is the rendered form of GlobalProcessType in annotation
// and label report keys (both JSON and single-flag). Real process types cannot
@@ -138,42 +139,164 @@ func ReportSingleApp(appName string, format string, infoFlag string) error {
})
}
// ReportAutoscalingAuthSingleApp is an internal function that displays the scheduler-k3s autoscaling-auth report for one app
func ReportAutoscalingAuthSingleApp(appName string, format string, includeMetadata bool) error {
properties, err := common.PropertyGetAllByPrefix("scheduler-k3s", appName, TriggerAuthPropertyPrefix)
if err != nil {
return fmt.Errorf("Unable to get property list: %w", err)
// autoscalingAuthReportEntry is a parsed trigger authentication metadata entry.
type autoscalingAuthReportEntry struct {
Trigger string
MetadataKey string
Value string
}
// ReportAutoscalingAuthSingleApp displays the scheduler-k3s autoscaling-auth report for one app.
func ReportAutoscalingAuthSingleApp(appName string, format string, includeMetadata bool, infoFlag string) error {
if appName != "--global" {
if err := common.VerifyAppName(appName); err != nil {
return err
}
}
infoFlags := map[string]string{}
entries, err := collectAutoscalingAuthEntries(appName)
if err != nil {
return err
}
return renderAutoscalingAuthReport(autoscalingAuthRenderInput{
AppName: appName,
Entries: entries,
Format: format,
IncludeMetadata: includeMetadata,
InfoFlag: infoFlag,
})
}
// collectAutoscalingAuthEntries scans the property store for trigger authentication metadata.
func collectAutoscalingAuthEntries(appName string) ([]autoscalingAuthReportEntry, error) {
properties, err := common.PropertyGetAllByPrefix("scheduler-k3s", appName, TriggerAuthPropertyPrefix)
if err != nil {
return nil, fmt.Errorf("Unable to get property list: %w", err)
}
entries := []autoscalingAuthReportEntry{}
for key, value := range properties {
metadataKey := strings.TrimPrefix(key, TriggerAuthPropertyPrefix)
authType := strings.SplitN(metadataKey, ".", 2)[0]
if authType == "" {
parts := strings.SplitN(metadataKey, ".", 2)
if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
continue
}
infoFlags[authType] = "configured"
if includeMetadata {
infoFlags[strings.ReplaceAll(metadataKey, ".", "-")] = value
entries = append(entries, autoscalingAuthReportEntry{
Trigger: parts[0],
MetadataKey: parts[1],
Value: value,
})
}
return entries, nil
}
type autoscalingAuthRenderInput struct {
AppName string
Entries []autoscalingAuthReportEntry
Format string
IncludeMetadata bool
InfoFlag string
}
// renderAutoscalingAuthReport dispatches to stdout/json/single-flag rendering for trigger auth.
func renderAutoscalingAuthReport(input autoscalingAuthRenderInput) error {
if input.Format != "stdout" && input.Format != "json" {
return fmt.Errorf("Invalid format: %s", input.Format)
}
if input.Format == "json" && input.InfoFlag != "" {
return fmt.Errorf("--format flag cannot be specified when specifying an info flag")
}
flatValues := map[string]string{}
flagToValue := map[string]string{}
flagPrefix := "--" + autoscalingAuthReportType + "."
for _, entry := range input.Entries {
composedKey := entry.Trigger + "." + entry.MetadataKey
flatValues[composedKey] = entry.Value
flagToValue[flagPrefix+composedKey] = entry.Value
}
if input.InfoFlag != "" {
value, ok := flagToValue[input.InfoFlag]
if !ok {
validFlags := []string{}
for flag := range flagToValue {
validFlags = append(validFlags, flag)
}
sort.Strings(validFlags)
return fmt.Errorf("Invalid flag passed, valid flags: %s", strings.Join(validFlags, ", "))
}
if value != "" {
fmt.Println(tokenMask)
} else {
fmt.Println("")
}
return nil
}
if input.Format == "json" {
b, err := json.Marshal(flatValues)
if err != nil {
return fmt.Errorf("Unable to marshal json: %w", err)
}
fmt.Println(string(b))
return nil
}
triggers := map[string]bool{}
for _, entry := range input.Entries {
triggers[entry.Trigger] = true
}
triggerKeys := []string{}
for trigger := range triggers {
triggerKeys = append(triggerKeys, trigger)
}
sort.Strings(triggerKeys)
common.LogInfo2Quiet(fmt.Sprintf("%s autoscaling-auth information", input.AppName))
if len(triggerKeys) == 0 {
return nil
}
length := 31
if input.IncludeMetadata {
for _, entry := range input.Entries {
label := fmt.Sprintf("%s %s:", common.UcFirst(entry.Trigger), entry.MetadataKey)
if len(label) > length {
length = len(label)
}
}
}
flagKeys := []string{}
for flagKey := range infoFlags {
flagKeys = append(flagKeys, flagKey)
for _, trigger := range triggerKeys {
label := fmt.Sprintf("%s:", common.UcFirst(trigger))
common.LogVerbose(fmt.Sprintf("%s%s", common.RightPad(label, length, " "), "configured"))
if !input.IncludeMetadata {
continue
}
triggerEntries := []autoscalingAuthReportEntry{}
for _, entry := range input.Entries {
if entry.Trigger == trigger {
triggerEntries = append(triggerEntries, entry)
}
}
sort.Slice(triggerEntries, func(i, j int) bool {
return triggerEntries[i].MetadataKey < triggerEntries[j].MetadataKey
})
for _, entry := range triggerEntries {
label := fmt.Sprintf("%s %s:", common.UcFirst(entry.Trigger), entry.MetadataKey)
common.LogVerbose(fmt.Sprintf("%s%s", common.RightPad(label, length, " "), entry.Value))
}
}
return common.ReportSingleApp(common.ReportSingleAppInput{
ReportType: "scheduler-k3s",
AppName: appName,
InfoFlags: infoFlags,
InfoFlagKeys: flagKeys,
Format: format,
TrimPrefix: true,
UppercaseFirstCharacter: true,
EmitLegacyPrefix: true,
})
return nil
}
// ExtractReportInfoFlag scans arguments for a single info flag whose name starts with

View File

@@ -0,0 +1,271 @@
package scheduler_k3s
import (
"bytes"
"encoding/json"
"io"
"os"
"strings"
"testing"
"github.com/dokku/dokku/plugins/common"
)
func setupReportTest(t *testing.T, apps ...string) {
t.Helper()
t.Setenv("PLUGIN_PATH", "/var/lib/dokku/plugins")
t.Setenv("PLUGIN_ENABLED_PATH", "/var/lib/dokku/plugins/enabled")
t.Setenv("DOKKU_LIB_ROOT", t.TempDir())
t.Setenv("DOKKU_SYSTEM_USER", "root")
t.Setenv("DOKKU_SYSTEM_GROUP", "root")
dokkuRoot := t.TempDir()
t.Setenv("DOKKU_ROOT", dokkuRoot)
if err := common.PropertySetup("scheduler-k3s"); err != nil {
t.Fatalf("PropertySetup: %v", err)
}
for _, appName := range apps {
if err := os.MkdirAll(dokkuRoot+"/"+appName, 0o755); err != nil {
t.Fatalf("MkdirAll: %v", err)
}
}
}
func captureStdout(t *testing.T, fn func()) string {
t.Helper()
orig := os.Stdout
r, w, err := os.Pipe()
if err != nil {
t.Fatalf("os.Pipe: %v", err)
}
os.Stdout = w
done := make(chan string)
go func() {
var buf bytes.Buffer
_, _ = io.Copy(&buf, r)
done <- buf.String()
}()
fn()
w.Close()
os.Stdout = orig
return <-done
}
func TestExtractReportInfoFlag(t *testing.T) {
t.Parallel()
tests := []struct {
name string
prefix string
args []string
wantArgs []string
wantFlag string
wantError string
}{
{
name: "no info flag",
prefix: "--scheduler-k3s-annotations.",
args: []string{"myapp", "--format", "json"},
wantArgs: []string{"myapp", "--format", "json"},
},
{
name: "single info flag",
prefix: "--scheduler-k3s-labels.",
args: []string{"myapp", "--scheduler-k3s-labels.global.deployment.foo"},
wantArgs: []string{"myapp"},
wantFlag: "--scheduler-k3s-labels.global.deployment.foo",
},
{
name: "multiple info flags",
prefix: "--scheduler-k3s-autoscaling-auth.",
args: []string{"myapp", "--scheduler-k3s-autoscaling-auth.datadog.apiKey", "--scheduler-k3s-autoscaling-auth.datadog.appKey"},
wantError: "only a single info flag may be specified",
},
}
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
gotArgs, gotFlag, err := ExtractReportInfoFlag(tc.prefix, tc.args)
if tc.wantError != "" {
if err == nil || !strings.Contains(err.Error(), tc.wantError) {
t.Fatalf("expected error containing %q, got %v", tc.wantError, err)
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if gotFlag != tc.wantFlag {
t.Fatalf("info flag = %q, want %q", gotFlag, tc.wantFlag)
}
if strings.Join(gotArgs, ",") != strings.Join(tc.wantArgs, ",") {
t.Fatalf("passthrough args = %v, want %v", gotArgs, tc.wantArgs)
}
})
}
}
func TestRenderProcessType(t *testing.T) {
t.Parallel()
if got := renderProcessType(GlobalProcessType); got != reportProcessTypeGlobal {
t.Fatalf("renderProcessType(GlobalProcessType) = %q, want %q", got, reportProcessTypeGlobal)
}
if got := renderProcessType("web"); got != "web" {
t.Fatalf("renderProcessType(\"web\") = %q, want %q", got, "web")
}
}
func TestRenderAnnotationsLabelsReportJSON(t *testing.T) {
out := captureStdout(t, func() {
err := renderAnnotationsLabelsReport(annotationsLabelsRenderInput{
AppName: "myapp",
ReportType: annotationsReportType,
Heading: "annotations",
RowLabel: "Annotation",
Entries: []annotationsLabelsReportEntry{
{ProcessType: GlobalProcessType, ResourceType: "deployment", Key: "foo", Value: "bar"},
{ProcessType: "web", ResourceType: "deployment", Key: "baz", Value: "qux"},
},
Format: "json",
})
if err != nil {
t.Fatalf("renderAnnotationsLabelsReport returned error: %v", err)
}
})
var got map[string]string
if err := json.Unmarshal([]byte(strings.TrimSpace(out)), &got); err != nil {
t.Fatalf("output is not valid JSON: %v\noutput: %s", err, out)
}
want := map[string]string{
"global.deployment.foo": "bar",
"web.deployment.baz": "qux",
}
for key, value := range want {
if got[key] != value {
t.Fatalf("expected %q=%q, got %q=%q", key, value, key, got[key])
}
}
}
func TestRenderAutoscalingAuthReportJSON(t *testing.T) {
out := captureStdout(t, func() {
err := renderAutoscalingAuthReport(autoscalingAuthRenderInput{
AppName: "myapp",
Entries: []autoscalingAuthReportEntry{
{Trigger: "datadog", MetadataKey: "apiKey", Value: "secret-1"},
{Trigger: "datadog", MetadataKey: "appKey", Value: "secret-2"},
},
Format: "json",
})
if err != nil {
t.Fatalf("renderAutoscalingAuthReport returned error: %v", err)
}
})
var got map[string]string
if err := json.Unmarshal([]byte(strings.TrimSpace(out)), &got); err != nil {
t.Fatalf("output is not valid JSON: %v\noutput: %s", err, out)
}
want := map[string]string{
"datadog.apiKey": "secret-1",
"datadog.appKey": "secret-2",
}
for key, value := range want {
if got[key] != value {
t.Fatalf("expected %q=%q, got %q=%q", key, value, key, got[key])
}
}
}
func TestReportAutoscalingAuthSingleAppInfoFlag(t *testing.T) {
setupReportTest(t, "myapp")
if err := common.PropertyWrite("scheduler-k3s", "myapp", "trigger-auth.datadog.apiKey", "secret-1"); err != nil {
t.Fatalf("PropertyWrite: %v", err)
}
out := captureStdout(t, func() {
err := ReportAutoscalingAuthSingleApp("myapp", "stdout", false, "--scheduler-k3s-autoscaling-auth.datadog.apiKey")
if err != nil {
t.Fatalf("ReportAutoscalingAuthSingleApp returned error: %v", err)
}
})
if strings.TrimSpace(out) != tokenMask {
t.Fatalf("info flag output = %q, want %q", strings.TrimSpace(out), tokenMask)
}
}
func TestCollectAutoscalingAuthEntriesFromProperties(t *testing.T) {
setupReportTest(t, "myapp")
if err := common.PropertyWrite("scheduler-k3s", "myapp", "trigger-auth.datadog.apiKey", "secret-1"); err != nil {
t.Fatalf("PropertyWrite apiKey: %v", err)
}
if err := common.PropertyWrite("scheduler-k3s", "myapp", "trigger-auth.datadog.appKey", "secret-2"); err != nil {
t.Fatalf("PropertyWrite appKey: %v", err)
}
entries, err := collectAutoscalingAuthEntries("myapp")
if err != nil {
t.Fatalf("collectAutoscalingAuthEntries returned error: %v", err)
}
if len(entries) != 2 {
t.Fatalf("expected 2 entries, got %d", len(entries))
}
}
func TestReportAutoscalingAuthGlobalJSON(t *testing.T) {
setupReportTest(t)
if err := common.PropertyWrite("scheduler-k3s", "--global", "trigger-auth.datadog.apiKey", "global-secret"); err != nil {
t.Fatalf("PropertyWrite: %v", err)
}
out := captureStdout(t, func() {
err := ReportAutoscalingAuthSingleApp("--global", "json", false, "")
if err != nil {
t.Fatalf("ReportAutoscalingAuthSingleApp returned error: %v", err)
}
})
var got map[string]string
if err := json.Unmarshal([]byte(strings.TrimSpace(out)), &got); err != nil {
t.Fatalf("output is not valid JSON: %v\noutput: %s", err, out)
}
if got["datadog.apiKey"] != "global-secret" {
t.Fatalf("expected datadog.apiKey=global-secret, got %v", got)
}
}
func TestRenderAutoscalingAuthReportStdoutIncludesMetadataValues(t *testing.T) {
out := captureStdout(t, func() {
err := renderAutoscalingAuthReport(autoscalingAuthRenderInput{
AppName: "myapp",
Entries: []autoscalingAuthReportEntry{
{Trigger: "datadog", MetadataKey: "apiKey", Value: "secret-1"},
},
Format: "stdout",
IncludeMetadata: true,
})
if err != nil {
t.Fatalf("renderAutoscalingAuthReport returned error: %v", err)
}
})
if !strings.Contains(out, "Datadog apiKey:") {
t.Fatalf("expected metadata key in stdout, got: %s", out)
}
if !strings.Contains(out, "secret-1") {
t.Fatalf("expected metadata value in stdout, got: %s", out)
}
}

View File

@@ -18,6 +18,7 @@ Additional commands:`
helpContent = `
scheduler-k3s:autoscaling-auth:set <app|--global> <trigger> [<--metadata key=value>...], Set or clear a scheduler-k3s autoscaling keda trigger authentication resource for an app
scheduler-k3s:autoscaling-auth:report [<app>|--global] [--format stdout|json] [--include-metadata], Displays a scheduler-k3s autoscaling auth report for one or more apps
scheduler-k3s:annotations:set <app|--global> <property> (<value>) [--process-type PROCESS_TYPE] <--resource-type RESOURCE_TYPE>, Set or clear an annotation for a given app/process-type/resource-type combination
scheduler-k3s:annotations:report [<app>|--global] [--format stdout|json] [--process-type PROCESS_TYPE] [--resource-type RESOURCE_TYPE], Displays a scheduler-k3s annotations report for one or more apps
scheduler-k3s:charts:report [<chart>] [--format stdout|json], Displays a scheduler-k3s chart override report

View File

@@ -66,14 +66,19 @@ func main() {
case "autoscaling-auth:report":
args := flag.NewFlagSet("scheduler-k3s:autoscaling-auth:report", flag.ExitOnError)
global := args.Bool("global", false, "--global: show the global report")
includeMetadata := args.Bool("include-metadata", false, "--include-metadata: include metadata in the report")
includeMetadata := args.Bool("include-metadata", false, "--include-metadata: include metadata keys and values in the report")
format := args.String("format", "stdout", "format: [ stdout | json ]")
args.Parse(os.Args[2:])
passthroughArgs, infoFlag, flagErr := scheduler_k3s.ExtractReportInfoFlag("--scheduler-k3s-autoscaling-auth.", os.Args[2:])
if flagErr != nil {
err = flagErr
break
}
args.Parse(passthroughArgs)
appName := args.Arg(0)
if *global {
appName = "--global"
}
err = scheduler_k3s.CommandAutoscalingAuthReport(appName, *format, *includeMetadata)
err = scheduler_k3s.CommandAutoscalingAuthReport(appName, *format, *includeMetadata, infoFlag)
case "charts:set":
args := flag.NewFlagSet("scheduler-k3s:charts:set", flag.ExitOnError)
args.Parse(os.Args[2:])

View File

@@ -108,7 +108,7 @@ func CommandAutoscalingAuthSet(appName string, trigger string, metadata map[stri
}
// CommandAutoscalingAuthReport displays a scheduler-k3s autoscaling keda trigger authentication report for one or more apps
func CommandAutoscalingAuthReport(appName string, format string, includeMetadata bool) error {
func CommandAutoscalingAuthReport(appName string, format string, includeMetadata bool, infoFlag string) error {
if len(appName) == 0 {
apps, err := common.DokkuApps()
if err != nil {
@@ -119,14 +119,14 @@ func CommandAutoscalingAuthReport(appName string, format string, includeMetadata
return err
}
for _, app := range apps {
if err := ReportAutoscalingAuthSingleApp(app, format, includeMetadata); err != nil {
if err := ReportAutoscalingAuthSingleApp(app, format, includeMetadata, infoFlag); err != nil {
return err
}
}
return nil
}
return ReportAutoscalingAuthSingleApp(appName, format, includeMetadata)
return ReportAutoscalingAuthSingleApp(appName, format, includeMetadata, infoFlag)
}
// CommandAnnotationsReport displays a scheduler-k3s annotations report for one or more apps

View File

@@ -96,3 +96,20 @@ teardown() {
assert_success
assert_output "$value"
}
@test "(scheduler-k3s:annotations:report) rejects invalid format and info-flag combinations" {
run /bin/bash -c "dokku scheduler-k3s:annotations:report $TEST_APP --format yaml"
assert_failure
assert_output_contains "Invalid format"
run /bin/bash -c "dokku scheduler-k3s:annotations:set $TEST_APP --resource-type deployment foo bar"
assert_success
run /bin/bash -c "dokku scheduler-k3s:annotations:report $TEST_APP --format json --scheduler-k3s-annotations.global.deployment.foo"
assert_failure
assert_output_contains "--format flag cannot be specified when specifying an info flag"
run /bin/bash -c "dokku scheduler-k3s:annotations:report $TEST_APP --scheduler-k3s-annotations.global.deployment.missing"
assert_failure
assert_output_contains "Invalid flag passed"
}

View File

@@ -2,6 +2,22 @@
load test_helper
scheduler_k3s_seed_trigger_auth() {
local scope="$1"
local trigger="$2"
local key="$3"
local value="$4"
local dir="/var/lib/dokku/config/scheduler-k3s/$scope"
sudo mkdir -p "$dir"
echo -n "$value" | sudo tee "$dir/trigger-auth.${trigger}.${key}" >/dev/null
}
scheduler_k3s_clear_trigger_auth() {
local scope="$1"
local trigger="$2"
sudo rm -f "/var/lib/dokku/config/scheduler-k3s/$scope/trigger-auth.${trigger}."* 2>/dev/null || true
}
setup() {
global_setup
dokku apps:create $TEST_APP >/dev/null 2>/dev/null || true
@@ -10,7 +26,9 @@ setup() {
teardown() {
dokku scheduler-k3s:autoscaling-auth:set $TEST_APP datadog >/dev/null 2>/dev/null || true
dokku scheduler-k3s:autoscaling-auth:set $TEST_APP memory >/dev/null 2>/dev/null || true
dokku scheduler-k3s:autoscaling-auth:set ${TEST_APP}-2 datadog >/dev/null 2>/dev/null || true
scheduler_k3s_clear_trigger_auth "--global" "datadog"
dokku --force apps:destroy $TEST_APP >/dev/null 2>/dev/null || true
dokku --force apps:destroy ${TEST_APP}-2 >/dev/null 2>/dev/null || true
global_teardown
@@ -24,7 +42,110 @@ teardown() {
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report"
assert_success
assert_output_contains "$TEST_APP scheduler-k3s information"
assert_output_contains "${TEST_APP}-2 scheduler-k3s information"
assert_output_contains "$TEST_APP autoscaling-auth information"
assert_output_contains "${TEST_APP}-2 autoscaling-auth information"
assert_output_contains "Datadog:" 2
}
@test "(scheduler-k3s:autoscaling-auth:report) lists metadata in json and clears after unset" {
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:set $TEST_APP datadog --metadata apiKey=secret-1 --metadata appKey=secret-2"
assert_success
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report $TEST_APP --format json | jq -r '.\"datadog.apiKey\"'"
assert_success
assert_output "secret-1"
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report $TEST_APP --format json | jq -r '.\"datadog.appKey\"'"
assert_success
assert_output "secret-2"
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report $TEST_APP --scheduler-k3s-autoscaling-auth.datadog.apiKey"
assert_success
assert_output "*******"
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report $TEST_APP"
assert_success
assert_output_contains "Datadog:"
assert_output_not_contains "Datadog apiKey:"
assert_output_not_contains "secret-1"
assert_output_not_contains "secret-2"
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report $TEST_APP --include-metadata"
assert_success
assert_output_contains "Datadog apiKey:"
assert_output_contains "secret-1"
assert_output_contains "secret-2"
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:set $TEST_APP datadog"
assert_success
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report $TEST_APP --format json"
assert_success
assert_output "{}"
}
@test "(scheduler-k3s:autoscaling-auth:report) stdout includes metadata values with --include-metadata" {
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:set $TEST_APP datadog --metadata apiKey=super-secret-value"
assert_success
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report $TEST_APP"
assert_success
assert_output_contains "Datadog:"
assert_output_contains "configured"
assert_output_not_contains "Datadog apiKey:"
assert_output_not_contains "super-secret-value"
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report $TEST_APP --include-metadata"
assert_success
assert_output_contains "Datadog apiKey:"
assert_output_contains "super-secret-value"
}
@test "(scheduler-k3s:autoscaling-auth:report) reports multiple triggers in json" {
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:set $TEST_APP datadog --metadata apiKey=secret-1"
assert_success
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:set $TEST_APP memory --metadata some-key=some-value"
assert_success
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report $TEST_APP --format json | jq -r 'keys | sort | join(\",\")'"
assert_success
assert_output "datadog.apiKey,memory.some-key"
}
@test "(scheduler-k3s:autoscaling-auth:report) supports --global scope" {
scheduler_k3s_seed_trigger_auth "--global" "datadog" "apiKey" "global-secret"
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report --global --format json | jq -r '.\"datadog.apiKey\"'"
assert_success
assert_output "global-secret"
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report --global --include-metadata"
assert_success
assert_output_contains "--global autoscaling-auth information"
assert_output_contains "Datadog:"
assert_output_contains "Datadog apiKey:"
assert_output_contains "global-secret"
}
@test "(scheduler-k3s:autoscaling-auth:report) returns empty json for unconfigured app" {
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report $TEST_APP --format json"
assert_success
assert_output "{}"
}
@test "(scheduler-k3s:autoscaling-auth:report) rejects invalid format and info-flag combinations" {
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report $TEST_APP --format yaml"
assert_failure
assert_output_contains "Invalid format"
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:set $TEST_APP datadog --metadata apiKey=secret-1"
assert_success
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report $TEST_APP --format json --scheduler-k3s-autoscaling-auth.datadog.apiKey"
assert_failure
assert_output_contains "--format flag cannot be specified when specifying an info flag"
run /bin/bash -c "dokku scheduler-k3s:autoscaling-auth:report $TEST_APP --scheduler-k3s-autoscaling-auth.datadog.missing"
assert_failure
assert_output_contains "Invalid flag passed"
}

View File

@@ -96,3 +96,20 @@ teardown() {
assert_success
assert_output "$value"
}
@test "(scheduler-k3s:labels:report) rejects invalid format and info-flag combinations" {
run /bin/bash -c "dokku scheduler-k3s:labels:report $TEST_APP --format yaml"
assert_failure
assert_output_contains "Invalid format"
run /bin/bash -c "dokku scheduler-k3s:labels:set $TEST_APP --resource-type deployment foo bar"
assert_success
run /bin/bash -c "dokku scheduler-k3s:labels:report $TEST_APP --format json --scheduler-k3s-labels.global.deployment.foo"
assert_failure
assert_output_contains "--format flag cannot be specified when specifying an info flag"
run /bin/bash -c "dokku scheduler-k3s:labels:report $TEST_APP --scheduler-k3s-labels.global.deployment.missing"
assert_failure
assert_output_contains "Invalid flag passed"
}