feat: add scheduler-k3s annotations:report and labels:report

The scheduler-k3s plugin exposes `annotations:set` and `labels:set` but no matching report subcommands, so scripts could not inspect the configured state for idempotent management without reading the property files directly. The new `scheduler-k3s:annotations:report` and `scheduler-k3s:labels:report` surface the configured entries with stdout, JSON, single-flag query, and `--process-type` / `--resource-type` filtering, mirroring the recently added `scheduler-k3s:charts:report`. The literal `GlobalProcessType` value `--global` is rendered as `global` in report keys to avoid leading dashes. The `scheduler-k3s:autoscaling-auth:report` command is updated alongside to loop over every app when no app and no `--global` flag is provided, matching the convention used by `scheduler-k3s:report`.
This commit is contained in:
Jose Diaz-Gonzalez
2026-05-30 20:12:00 -04:00
parent 4346a18194
commit 5dbb2951bb
10 changed files with 712 additions and 19 deletions

View File

@@ -5,8 +5,9 @@
```
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: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 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:charts:report [<chart>] [--format stdout|json] # Displays a scheduler-k3s chart override report
scheduler-k3s:charts:set <chart-name.property> (<value>) # Set or clear a chart-specific helm value
scheduler-k3s:cluster:add [ssh://user@host:port] # Adds a server node to a Dokku-managed cluster
@@ -15,6 +16,7 @@ scheduler-k3s:cluster:remove [node-id] # Removes client node to a D
scheduler-k3s:ensure-charts # Ensures the k3s charts are installed
scheduler-k3s:initialize # Initializes a cluster
scheduler-k3s:labels:set <app|--global> <property> (<value>) [--process-type PROCESS_TYPE] <--resource-type RESOURCE_TYPE> # Set or clear a label for a given app/process-type/resource-type combination
scheduler-k3s:labels:report [<app>|--global] [--format stdout|json] [--process-type PROCESS_TYPE] [--resource-type RESOURCE_TYPE] # Displays a scheduler-k3s labels report for one or more apps
scheduler-k3s:profiles:add <profile> [--role ROLE] [--insecure-allow-unknown-hosts] [--taint-scheduling] [--kubelet-args KUBELET_ARGS] Adds a node profile to the k3s cluster
scheduler-k3s:profiles:list [--format json|stdout] # Lists all node profiles in the k3s cluster
scheduler-k3s:profiles:remove <profile> # Removes a node profile from the k3s cluster
@@ -387,6 +389,35 @@ dokku scheduler-k3s:annotations:set node-js-app annotation.key --resource-type d
A `ps:restart` is required after removing annotations in order to remove them from running resources.
#### Displaying annotations
Configured annotations can be inspected with the `scheduler-k3s:annotations:report` command. Without arguments, it iterates every app and prints all annotations. Passing an app name (or `--global`) scopes the report:
```shell
dokku scheduler-k3s:annotations:report
dokku scheduler-k3s:annotations:report node-js-app
dokku scheduler-k3s:annotations:report --global
```
`--process-type` and `--resource-type` flags narrow the output to a specific scope, matching the flags accepted by `scheduler-k3s:annotations:set`:
```shell
dokku scheduler-k3s:annotations:report node-js-app --resource-type deployment
dokku scheduler-k3s:annotations:report node-js-app --process-type web --resource-type deployment
```
JSON output emits flat keys of the form `{process_type}.{resource_type}.{annotation_key}`. The literal `--global` process type is rendered as `global` to keep keys free of leading dashes:
```shell
dokku scheduler-k3s:annotations:report node-js-app --format json
```
A single value can also be read directly with a flag of the form `--scheduler-k3s-annotations.{process_type}.{resource_type}.{annotation_key}`:
```shell
dokku scheduler-k3s:annotations:report node-js-app --scheduler-k3s-annotations.global.deployment.annotation.key
```
#### Setting Labels
Dokku injects certain labels into each created resource by default, but it may be necessary to inject others for tighter integration with third-party tools. The `scheduler-k3s:labels:set` command can be used to perform this task. The command takes an app name and a required `--resource-type` flag.
@@ -428,6 +459,20 @@ dokku scheduler-k3s:labels:set node-js-app label.key --resource-type deployment
A `ps:restart` is required after removing labels in order to remove them from running resources.
#### Displaying labels
Configured labels can be inspected with the `scheduler-k3s:labels:report` command. The surface mirrors `scheduler-k3s:annotations:report`:
```shell
dokku scheduler-k3s:labels:report
dokku scheduler-k3s:labels:report node-js-app
dokku scheduler-k3s:labels:report --global
dokku scheduler-k3s:labels:report node-js-app --resource-type deployment
dokku scheduler-k3s:labels:report node-js-app --process-type web --resource-type deployment
dokku scheduler-k3s:labels:report node-js-app --format json
dokku scheduler-k3s:labels:report node-js-app --scheduler-k3s-labels.global.deployment.label.key
```
### Autoscaling
#### Workload Autoscaling
@@ -566,10 +611,12 @@ dokku scheduler-k3s:autoscaling-auth:set $APP $TRIGGER_TYPE
##### Displaying an Authentication Resource report
To see a list of authentication resources managed by Dokku, run the `scheduler-k3s:autoscaling-auth:report` command.
To see a list of authentication resources managed by Dokku, run the `scheduler-k3s:autoscaling-auth:report` command. Without arguments, the report iterates every app; passing an app name (or `--global`) scopes the report:
```shell
dokku scheduler-k3s:autoscaling-auth:report
dokku scheduler-k3s:autoscaling-auth:report node-js-app
dokku scheduler-k3s:autoscaling-auth:report --global
```
```

View File

@@ -1,4 +1,4 @@
SUBCOMMANDS = subcommands/annotations:set subcommands/autoscaling-auth:set subcommands/autoscaling-auth:report subcommands/charts:report subcommands/charts:set subcommands/cluster:add subcommands/cluster:list subcommands/cluster:remove subcommands/ensure-charts subcommands/initialize subcommands/labels:set subcommands/profiles:add subcommands/profiles:list subcommands/profiles:remove subcommands/report subcommands/set subcommands/show-kubeconfig subcommands/uninstall
SUBCOMMANDS = subcommands/annotations:set subcommands/annotations:report subcommands/autoscaling-auth:set subcommands/autoscaling-auth:report subcommands/charts:report subcommands/charts:set subcommands/cluster:add subcommands/cluster:list subcommands/cluster:remove subcommands/ensure-charts subcommands/initialize subcommands/labels:set subcommands/labels:report subcommands/profiles:add subcommands/profiles:list subcommands/profiles:remove subcommands/report subcommands/set subcommands/show-kubeconfig subcommands/uninstall
TRIGGERS = triggers/core-post-deploy triggers/core-post-extract triggers/install triggers/post-app-clone-setup triggers/post-app-rename-setup triggers/post-certs-update triggers/post-certs-remove triggers/post-create triggers/post-delete triggers/report triggers/scheduler-app-status triggers/scheduler-deploy triggers/scheduler-enter triggers/scheduler-is-deployed triggers/scheduler-logs triggers/scheduler-proxy-config triggers/scheduler-proxy-logs triggers/scheduler-post-delete triggers/scheduler-run triggers/scheduler-run-list triggers/scheduler-stop triggers/scheduler-cron-write triggers/storage-create triggers/storage-destroy triggers/storage-status triggers/scheduler-storage-exec
BUILD = commands subcommands triggers
PLUGIN_NAME = scheduler-k3s

View File

@@ -1,12 +1,24 @@
package scheduler_k3s
import (
"encoding/json"
"fmt"
"sort"
"strings"
"github.com/dokku/dokku/plugins/common"
)
const (
annotationsReportType = "scheduler-k3s-annotations"
labelsReportType = "scheduler-k3s-labels"
// reportProcessTypeGlobal is the rendered form of GlobalProcessType in annotation
// and label report keys (both JSON and single-flag). Real process types cannot
// collide because they cannot contain "--".
reportProcessTypeGlobal = "global"
)
// tokenMask is shown in place of the raw token value in default stdout output.
const tokenMask = "*******"
@@ -161,6 +173,304 @@ func ReportAutoscalingAuthSingleApp(appName string, format string, includeMetada
})
}
// ExtractReportInfoFlag scans arguments for a single info flag whose name starts with
// the given prefix (e.g. "--scheduler-k3s-annotations.") and returns it separately from
// the remaining passthrough arguments. Returns an error if more than one matching flag
// is present. Matching args are removed from the passthrough list so the caller's
// flag.FlagSet sees only its own flags and positional arguments.
func ExtractReportInfoFlag(prefix string, arguments []string) ([]string, string, error) {
passthrough := []string{}
infoFlag := ""
for _, argument := range arguments {
if strings.HasPrefix(argument, prefix) {
if infoFlag != "" {
return nil, "", fmt.Errorf("only a single info flag may be specified")
}
infoFlag = argument
continue
}
passthrough = append(passthrough, argument)
}
return passthrough, infoFlag, nil
}
// annotationsLabelsReportEntry is a parsed (processType, resourceType, key) triple
// produced when scanning the property store for annotations or labels.
type annotationsLabelsReportEntry struct {
ProcessType string
ResourceType string
Key string
Value string
}
// ReportAnnotationsSingleApp displays the scheduler-k3s annotations report for one app.
func ReportAnnotationsSingleApp(appName string, format string, processType string, resourceType string, infoFlag string) error {
if appName != "--global" {
if err := common.VerifyAppName(appName); err != nil {
return err
}
}
entries, err := collectAnnotationsEntries(appName, processType, resourceType)
if err != nil {
return err
}
return renderAnnotationsLabelsReport(annotationsLabelsRenderInput{
AppName: appName,
ReportType: annotationsReportType,
Heading: "annotations",
RowLabel: "Annotation",
Entries: entries,
Format: format,
InfoFlag: infoFlag,
})
}
// ReportLabelsSingleApp displays the scheduler-k3s labels report for one app.
func ReportLabelsSingleApp(appName string, format string, processType string, resourceType string, infoFlag string) error {
if appName != "--global" {
if err := common.VerifyAppName(appName); err != nil {
return err
}
}
entries, err := collectLabelsEntries(appName, processType, resourceType)
if err != nil {
return err
}
return renderAnnotationsLabelsReport(annotationsLabelsRenderInput{
AppName: appName,
ReportType: labelsReportType,
Heading: "labels",
RowLabel: "Label",
Entries: entries,
Format: format,
InfoFlag: infoFlag,
})
}
// collectAnnotationsEntries scans the property store for annotation entries on appName,
// optionally filtered by processType/resourceType.
func collectAnnotationsEntries(appName string, processType string, resourceType string) ([]annotationsLabelsReportEntry, error) {
properties, err := common.PropertyGetAllByPrefix("scheduler-k3s", appName, "")
if err != nil {
return nil, fmt.Errorf("Unable to get property list: %w", err)
}
knownResourceTypes := map[string]bool{}
for _, rt := range AnnotationResourceTypes {
knownResourceTypes[rt] = true
}
entries := []annotationsLabelsReportEntry{}
for propertyName := range properties {
if isReservedAnnotationProperty(propertyName) {
continue
}
dot := strings.LastIndex(propertyName, ".")
if dot <= 0 || dot == len(propertyName)-1 {
continue
}
propProcessType := propertyName[:dot]
propResourceType := propertyName[dot+1:]
if !knownResourceTypes[propResourceType] {
continue
}
if processType != "" && propProcessType != processType {
continue
}
if resourceType != "" && propResourceType != resourceType {
continue
}
annotationMap, err := getAnnotation(appName, propProcessType, propResourceType)
if err != nil {
return nil, fmt.Errorf("Unable to read annotation %s: %w", propertyName, err)
}
for key, value := range annotationMap {
entries = append(entries, annotationsLabelsReportEntry{
ProcessType: propProcessType,
ResourceType: propResourceType,
Key: key,
Value: value,
})
}
}
return entries, nil
}
// collectLabelsEntries scans the property store for label entries on appName,
// optionally filtered by processType/resourceType.
func collectLabelsEntries(appName string, processType string, resourceType string) ([]annotationsLabelsReportEntry, error) {
properties, err := common.PropertyGetAllByPrefix("scheduler-k3s", appName, "labels.")
if err != nil {
return nil, fmt.Errorf("Unable to get property list: %w", err)
}
knownResourceTypes := map[string]bool{}
for _, rt := range LabelResourceTypes {
knownResourceTypes[rt] = true
}
entries := []annotationsLabelsReportEntry{}
for propertyName := range properties {
suffix := strings.TrimPrefix(propertyName, "labels.")
dot := strings.LastIndex(suffix, ".")
if dot <= 0 || dot == len(suffix)-1 {
continue
}
propProcessType := suffix[:dot]
propResourceType := suffix[dot+1:]
if !knownResourceTypes[propResourceType] {
continue
}
if processType != "" && propProcessType != processType {
continue
}
if resourceType != "" && propResourceType != resourceType {
continue
}
labelMap, err := getLabel(appName, propProcessType, propResourceType)
if err != nil {
return nil, fmt.Errorf("Unable to read label %s: %w", propertyName, err)
}
for key, value := range labelMap {
entries = append(entries, annotationsLabelsReportEntry{
ProcessType: propProcessType,
ResourceType: propResourceType,
Key: key,
Value: value,
})
}
}
return entries, nil
}
func isReservedAnnotationProperty(propertyName string) bool {
for _, prefix := range reservedAnnotationPrefixes {
if strings.HasPrefix(propertyName, prefix) {
return true
}
}
return false
}
type annotationsLabelsRenderInput struct {
AppName string
ReportType string
// Heading is the plural noun used in stdout headers (e.g. "annotations", "labels").
Heading string
// RowLabel is the singular noun used to prefix each stdout row (e.g. "Annotation").
RowLabel string
Entries []annotationsLabelsReportEntry
Format string
InfoFlag string
}
// renderAnnotationsLabelsReport dispatches to stdout/json/single-flag rendering for the
// annotations and labels reports.
func renderAnnotationsLabelsReport(input annotationsLabelsRenderInput) 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 := "--" + input.ReportType + "."
for _, entry := range input.Entries {
composedKey := renderProcessType(entry.ProcessType) + "." + entry.ResourceType + "." + entry.Key
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, ", "))
}
fmt.Println(value)
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
}
entriesByGroup := map[string][]annotationsLabelsReportEntry{}
for _, entry := range input.Entries {
groupKey := renderProcessType(entry.ProcessType) + "/" + entry.ResourceType
entriesByGroup[groupKey] = append(entriesByGroup[groupKey], entry)
}
groupKeys := []string{}
for groupKey := range entriesByGroup {
groupKeys = append(groupKeys, groupKey)
}
sort.Strings(groupKeys)
common.LogInfo2Quiet(fmt.Sprintf("%s %s information", input.AppName, input.Heading))
if len(groupKeys) == 0 {
return nil
}
for _, groupKey := range groupKeys {
groupEntries := entriesByGroup[groupKey]
sort.Slice(groupEntries, func(i, j int) bool {
return groupEntries[i].Key < groupEntries[j].Key
})
length := 31
for _, entry := range groupEntries {
label := fmt.Sprintf("%s (%s) %s:", input.RowLabel, groupKey, entry.Key)
if len(label) > length {
length = len(label)
}
}
for _, entry := range groupEntries {
label := fmt.Sprintf("%s (%s) %s:", input.RowLabel, groupKey, entry.Key)
common.LogVerbose(fmt.Sprintf("%s%s", common.RightPad(label, length, " "), entry.Value))
}
}
return nil
}
// renderProcessType normalizes the in-storage process type for display in JSON keys,
// stdout headers, and single-flag lookups. GlobalProcessType (literal "--global") is
// rendered as "global"; real process types pass through unchanged.
func renderProcessType(processType string) string {
if processType == GlobalProcessType {
return reportProcessTypeGlobal
}
return processType
}
func reportComputedDeployTimeout(appName string) string {
return getComputedDeployTimeout(appName)
}

View File

@@ -52,6 +52,54 @@ const KubeConfigPath = "/etc/rancher/k3s/k3s.yaml"
const DefaultKubeContext = ""
const TriggerAuthPropertyPrefix = "trigger-auth."
// AnnotationResourceTypes lists the kubernetes resource types that scheduler-k3s
// supports user-provided annotations for. The order here is also the iteration order
// used when rendering reports.
var AnnotationResourceTypes = []string{
"certificate",
"cronjob",
"deployment",
"ingress",
"job",
"keda_scaled_object",
"keda_secret",
"keda_trigger_authentication",
"pod",
"secret",
"service",
"serviceaccount",
"traefik_ingressroute",
"traefik_middleware",
}
// LabelResourceTypes lists the kubernetes resource types that scheduler-k3s
// supports user-provided labels for. Differs from AnnotationResourceTypes because
// keda resources do not currently flow user labels through.
var LabelResourceTypes = []string{
"certificate",
"cronjob",
"deployment",
"ingress",
"job",
"pod",
"secret",
"service",
"serviceaccount",
"traefik_ingressroute",
"traefik_middleware",
}
// reservedAnnotationPrefixes lists property name prefixes that are not annotations
// even though their trailing segment may collide with an AnnotationResourceTypes value
// (e.g. "chart.cert-manager.deployment"). The annotations report uses this list to
// exclude such properties when scanning the property store.
var reservedAnnotationPrefixes = []string{
"chart.",
"labels.",
"node-profile-",
TriggerAuthPropertyPrefix,
}
var (
runtimeScheme = runtime.NewScheme()
codecs = serializer.NewCodecFactory(runtimeScheme)

View File

@@ -19,6 +19,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: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
scheduler-k3s:charts:set <chart-name.property> (<value>), Set or clear a chart-specific helm value
scheduler-k3s:cluster:add [--profile PROFILE] [--role ROLE] [--insecure-allow-unknown-hosts] [--server-ip SERVER_IP] [--taint-scheduling] [--kubelet-args KUBELET_ARGS] <ssh://user@host:port>, Adds a server node to a Dokku-managed cluster
@@ -27,6 +28,7 @@ Additional commands:`
scheduler-k3s:ensure-charts, Ensures the k3s charts are installed
scheduler-k3s:initialize [--server-ip SERVER_IP] [--taint-scheduling], Initializes a cluster
scheduler-k3s:labels:set <app|--global> <property> (<value>) [--process-type PROCESS_TYPE] <--resource-type RESOURCE_TYPE>, Set or clear a label for a given app/process-type/resource-type combination
scheduler-k3s:labels:report [<app>|--global] [--format stdout|json] [--process-type PROCESS_TYPE] [--resource-type RESOURCE_TYPE], Displays a scheduler-k3s labels report for one or more apps
scheduler-k3s:profiles:add <profile> [--role ROLE] [--insecure-allow-unknown-hosts] [--taint-scheduling] [--kubelet-args KUBELET_ARGS], Adds a node profile to the k3s cluster
scheduler-k3s:profiles:list [--format json|stdout], Lists all node profiles in the k3s cluster
scheduler-k3s:profiles:remove <profile>, Removes a node profile from the k3s cluster

View File

@@ -34,6 +34,23 @@ func main() {
}
err = scheduler_k3s.CommandAnnotationsSet(appName, *processType, *resourceType, property, value)
case "annotations:report":
args := flag.NewFlagSet("scheduler-k3s:annotations:report", flag.ExitOnError)
global := args.Bool("global", false, "--global: show the global report")
format := args.String("format", "stdout", "format: [ stdout | json ]")
processType := args.String("process-type", "", "--process-type: filter by process-type")
resourceType := args.String("resource-type", "", "--resource-type: filter by resource-type")
passthroughArgs, infoFlag, flagErr := scheduler_k3s.ExtractReportInfoFlag("--scheduler-k3s-annotations.", os.Args[2:])
if flagErr != nil {
err = flagErr
break
}
args.Parse(passthroughArgs)
appName := args.Arg(0)
if *global {
appName = "--global"
}
err = scheduler_k3s.CommandAnnotationsReport(appName, *format, *processType, *resourceType, infoFlag)
case "autoscaling-auth:set":
args := flag.NewFlagSet("scheduler-k3s:autoscaling-auth:set", flag.ExitOnError)
global := args.Bool("global", false, "--global: set a global property")
@@ -48,12 +65,15 @@ func main() {
err = scheduler_k3s.CommandAutoscalingAuthSet(appName, trigger, *metadata, *global)
case "autoscaling-auth:report":
args := flag.NewFlagSet("scheduler-k3s:autoscaling-auth:report", flag.ExitOnError)
global := args.Bool("global", false, "--global: show a global report")
global := args.Bool("global", false, "--global: show the global report")
includeMetadata := args.Bool("include-metadata", false, "--include-metadata: include metadata in the report")
format := args.String("format", "stdout", "format: [ stdout | json ]")
args.Parse(os.Args[2:])
appName := args.Arg(0)
err = scheduler_k3s.CommandAutoscalingAuthReport(appName, *format, *global, *includeMetadata)
if *global {
appName = "--global"
}
err = scheduler_k3s.CommandAutoscalingAuthReport(appName, *format, *includeMetadata)
case "charts:set":
args := flag.NewFlagSet("scheduler-k3s:charts:set", flag.ExitOnError)
args.Parse(os.Args[2:])
@@ -121,6 +141,23 @@ func main() {
}
err = scheduler_k3s.CommandLabelsSet(appName, *processType, *resourceType, property, value)
case "labels:report":
args := flag.NewFlagSet("scheduler-k3s:labels:report", flag.ExitOnError)
global := args.Bool("global", false, "--global: show the global report")
format := args.String("format", "stdout", "format: [ stdout | json ]")
processType := args.String("process-type", "", "--process-type: filter by process-type")
resourceType := args.String("resource-type", "", "--resource-type: filter by resource-type")
passthroughArgs, infoFlag, flagErr := scheduler_k3s.ExtractReportInfoFlag("--scheduler-k3s-labels.", os.Args[2:])
if flagErr != nil {
err = flagErr
break
}
args.Parse(passthroughArgs)
appName := args.Arg(0)
if *global {
appName = "--global"
}
err = scheduler_k3s.CommandLabelsReport(appName, *format, *processType, *resourceType, infoFlag)
case "profiles:add":
args := flag.NewFlagSet("scheduler-k3s:profiles:add", flag.ExitOnError)
role := args.String("role", "worker", "role: [ server | worker ]")

View File

@@ -124,26 +124,69 @@ 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, global bool, includeMetadata bool) error {
if len(appName) == 0 && !global {
return fmt.Errorf("Missing required app name or --global flag")
}
if len(appName) > 0 && global {
return fmt.Errorf("Cannot specify both app name and --global flag")
}
if !global {
if err := common.VerifyAppName(appName); err != nil {
func CommandAutoscalingAuthReport(appName string, format string, includeMetadata bool) 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 _, app := range apps {
if err := ReportAutoscalingAuthSingleApp(app, format, includeMetadata); err != nil {
return err
}
}
return nil
}
if len(appName) > 0 {
return ReportAutoscalingAuthSingleApp(appName, format, includeMetadata)
return ReportAutoscalingAuthSingleApp(appName, format, includeMetadata)
}
// CommandAnnotationsReport displays a scheduler-k3s annotations report for one or more apps
func CommandAnnotationsReport(appName string, format string, processType string, resourceType 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 _, app := range apps {
if err := ReportAnnotationsSingleApp(app, format, processType, resourceType, infoFlag); err != nil {
return err
}
}
return nil
}
return ReportAutoscalingAuthSingleApp("--global", format, includeMetadata)
return ReportAnnotationsSingleApp(appName, format, processType, resourceType, infoFlag)
}
// CommandLabelsReport displays a scheduler-k3s labels report for one or more apps
func CommandLabelsReport(appName string, format string, processType string, resourceType 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 _, app := range apps {
if err := ReportLabelsSingleApp(app, format, processType, resourceType, infoFlag); err != nil {
return err
}
}
return nil
}
return ReportLabelsSingleApp(appName, format, processType, resourceType, infoFlag)
}
// CommandInitialize initializes a k3s cluster on the local server

View File

@@ -0,0 +1,88 @@
#!/usr/bin/env bats
load test_helper
setup() {
global_setup
dokku apps:create $TEST_APP >/dev/null 2>/dev/null || true
}
teardown() {
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
for resource in deployment service pod cronjob job secret ingress serviceaccount; do
dokku scheduler-k3s:annotations:set --global --resource-type "$resource" foo "" >/dev/null 2>/dev/null || true
dokku scheduler-k3s:annotations:set --global --resource-type "$resource" bar "" >/dev/null 2>/dev/null || true
done
global_teardown
}
@test "(scheduler-k3s:annotations:report) lists annotations after set, clears them after unset" {
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 | jq -r '.\"global.deployment.foo\"'"
assert_success
assert_output "bar"
run /bin/bash -c "dokku scheduler-k3s:annotations:report $TEST_APP"
assert_success
assert_output_contains "$TEST_APP annotations information"
assert_output_contains "Annotation (global/deployment) foo:"
assert_output_contains "bar"
run /bin/bash -c "dokku scheduler-k3s:annotations:report $TEST_APP --scheduler-k3s-annotations.global.deployment.foo"
assert_success
assert_output "bar"
run /bin/bash -c "dokku scheduler-k3s:annotations:set $TEST_APP --resource-type deployment foo"
assert_success
run /bin/bash -c "dokku scheduler-k3s:annotations:report $TEST_APP --format json"
assert_success
assert_output "{}"
}
@test "(scheduler-k3s:annotations:report) honours --process-type and --resource-type filters" {
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:set $TEST_APP --process-type web --resource-type deployment baz qux"
assert_success
run /bin/bash -c "dokku scheduler-k3s:annotations:set $TEST_APP --resource-type service alpha beta"
assert_success
run /bin/bash -c "dokku scheduler-k3s:annotations:report $TEST_APP --resource-type deployment --format json | jq -r 'keys | sort | join(\",\")'"
assert_success
assert_output "global.deployment.foo,web.deployment.baz"
run /bin/bash -c "dokku scheduler-k3s:annotations:report $TEST_APP --process-type web --format json | jq -r 'keys | sort | join(\",\")'"
assert_success
assert_output "web.deployment.baz"
run /bin/bash -c "dokku scheduler-k3s:annotations:report $TEST_APP --process-type web --resource-type deployment --format json | jq -r '.\"web.deployment.baz\"'"
assert_success
assert_output "qux"
}
@test "(scheduler-k3s:annotations:report) supports --global scope and no-arg multi-app loop" {
run /bin/bash -c "dokku apps:create ${TEST_APP}-2"
assert_success
run /bin/bash -c "dokku scheduler-k3s:annotations:set --global --resource-type deployment foo global-val"
assert_success
run /bin/bash -c "dokku scheduler-k3s:annotations:set $TEST_APP --resource-type deployment foo app1-val"
assert_success
run /bin/bash -c "dokku scheduler-k3s:annotations:set ${TEST_APP}-2 --resource-type deployment bar app2-val"
assert_success
run /bin/bash -c "dokku scheduler-k3s:annotations:report --global --format json | jq -r '.\"global.deployment.foo\"'"
assert_success
assert_output "global-val"
run /bin/bash -c "dokku scheduler-k3s:annotations:report"
assert_success
assert_output_contains "$TEST_APP annotations information"
assert_output_contains "${TEST_APP}-2 annotations information"
assert_output_contains "app1-val"
assert_output_contains "app2-val"
}

View File

@@ -0,0 +1,30 @@
#!/usr/bin/env bats
load test_helper
setup() {
global_setup
dokku apps:create $TEST_APP >/dev/null 2>/dev/null || true
dokku apps:create ${TEST_APP}-2 >/dev/null 2>/dev/null || true
}
teardown() {
dokku scheduler-k3s:autoscaling-auth:set $TEST_APP datadog >/dev/null 2>/dev/null || true
dokku scheduler-k3s:autoscaling-auth:set ${TEST_APP}-2 datadog >/dev/null 2>/dev/null || true
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
}
@test "(scheduler-k3s:autoscaling-auth:report) no-arg loops all apps" {
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}-2 datadog --metadata apiKey=secret-2"
assert_success
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 "Datadog:" 2
}

View File

@@ -0,0 +1,88 @@
#!/usr/bin/env bats
load test_helper
setup() {
global_setup
dokku apps:create $TEST_APP >/dev/null 2>/dev/null || true
}
teardown() {
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
for resource in deployment service pod cronjob job secret ingress serviceaccount; do
dokku scheduler-k3s:labels:set --global --resource-type "$resource" foo "" >/dev/null 2>/dev/null || true
dokku scheduler-k3s:labels:set --global --resource-type "$resource" bar "" >/dev/null 2>/dev/null || true
done
global_teardown
}
@test "(scheduler-k3s:labels:report) lists labels after set, clears them after unset" {
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 | jq -r '.\"global.deployment.foo\"'"
assert_success
assert_output "bar"
run /bin/bash -c "dokku scheduler-k3s:labels:report $TEST_APP"
assert_success
assert_output_contains "$TEST_APP labels information"
assert_output_contains "Label (global/deployment) foo:"
assert_output_contains "bar"
run /bin/bash -c "dokku scheduler-k3s:labels:report $TEST_APP --scheduler-k3s-labels.global.deployment.foo"
assert_success
assert_output "bar"
run /bin/bash -c "dokku scheduler-k3s:labels:set $TEST_APP --resource-type deployment foo"
assert_success
run /bin/bash -c "dokku scheduler-k3s:labels:report $TEST_APP --format json"
assert_success
assert_output "{}"
}
@test "(scheduler-k3s:labels:report) honours --process-type and --resource-type filters" {
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:set $TEST_APP --process-type web --resource-type deployment baz qux"
assert_success
run /bin/bash -c "dokku scheduler-k3s:labels:set $TEST_APP --resource-type service alpha beta"
assert_success
run /bin/bash -c "dokku scheduler-k3s:labels:report $TEST_APP --resource-type deployment --format json | jq -r 'keys | sort | join(\",\")'"
assert_success
assert_output "global.deployment.foo,web.deployment.baz"
run /bin/bash -c "dokku scheduler-k3s:labels:report $TEST_APP --process-type web --format json | jq -r 'keys | sort | join(\",\")'"
assert_success
assert_output "web.deployment.baz"
run /bin/bash -c "dokku scheduler-k3s:labels:report $TEST_APP --process-type web --resource-type deployment --format json | jq -r '.\"web.deployment.baz\"'"
assert_success
assert_output "qux"
}
@test "(scheduler-k3s:labels:report) supports --global scope and no-arg multi-app loop" {
run /bin/bash -c "dokku apps:create ${TEST_APP}-2"
assert_success
run /bin/bash -c "dokku scheduler-k3s:labels:set --global --resource-type deployment foo global-val"
assert_success
run /bin/bash -c "dokku scheduler-k3s:labels:set $TEST_APP --resource-type deployment foo app1-val"
assert_success
run /bin/bash -c "dokku scheduler-k3s:labels:set ${TEST_APP}-2 --resource-type deployment bar app2-val"
assert_success
run /bin/bash -c "dokku scheduler-k3s:labels:report --global --format json | jq -r '.\"global.deployment.foo\"'"
assert_success
assert_output "global-val"
run /bin/bash -c "dokku scheduler-k3s:labels:report"
assert_success
assert_output_contains "$TEST_APP labels information"
assert_output_contains "${TEST_APP}-2 labels information"
assert_output_contains "app1-val"
assert_output_contains "app2-val"
}