From d41fa91fffd63fb7cf3e54539bc3b2cdb1dce7d9 Mon Sep 17 00:00:00 2001 From: Nicholas Yancey Date: Wed, 29 Jul 2026 14:22:11 -0400 Subject: [PATCH] Fix schedule create examples showing velero instead of oc oadp --- cmd/root.go | 13 +++++++++++++ cmd/root_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/cmd/root.go b/cmd/root.go index 429827a4d..9c849652d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -178,6 +178,14 @@ var veleroCommandPattern = regexp.MustCompile(`(?m)(?:^|[\s\x60])velero\s+(?:` + `(?:version|install|uninstall|plugin|snapshot-location|backup-location|restic|repo|client|completion|bug|debug|datamover)` + `)`) +// veleroCreateVerbFirstPattern matches upstream Velero's "velero create " example +// text (verb-first), which some commands hardcode instead of the actual resource-first +// invocation. For example, velero's schedule create command is invoked as +// "velero schedule create NAME", but its upstream Example text says "velero create schedule +// NAME". veleroCommandPattern above doesn't catch this ordering, so it's normalized to +// resource-first form here before the general replacement runs. +var veleroCreateVerbFirstPattern = regexp.MustCompile(`(^|[\s\x60\n])velero\s+create\s+(backup|restore|schedule)\b`) + // replaceVeleroCommandWithOADP performs context-aware replacement of "velero" with "oadp". // It only replaces "velero" when it's being used as a CLI command, not when referring to // the Velero project, server, or components. @@ -186,6 +194,11 @@ func replaceVeleroCommandWithOADP(text string) string { // Use "oc" as the CLI prefix since OADP is primarily used on OpenShift cliPrefix := "oc" + // Normalize verb-first "velero create " examples to resource-first + // "oc oadp create" before the general pattern runs, since the actual + // command is always invoked resource-first. + text = veleroCreateVerbFirstPattern.ReplaceAllString(text, "${1}"+cliPrefix+" oadp ${2} create") + // Replace "velero " patterns with "oc/kubectl oadp " result := veleroCommandPattern.ReplaceAllStringFunc(text, func(match string) string { // Preserve leading whitespace or backtick diff --git a/cmd/root_test.go b/cmd/root_test.go index 96cb819c4..fe741c11b 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -221,6 +221,34 @@ Use velero backup logs to check status`, } } +// TestReplaceVeleroWithOADP_ScheduleCreateVerbFirst tests that upstream Velero's +// verb-first "velero create schedule NAME" example text (a known upstream quirk in +// schedule/create.go) is normalized to the resource-first form that actually matches +// how the command is invoked, consistent with "backup create" and "restore create". +func TestReplaceVeleroWithOADP_ScheduleCreateVerbFirst(t *testing.T) { + cmd := &cobra.Command{ + Use: "test", + Example: ` # Create a backup every 6 hours. + velero create schedule NAME --schedule="0 */6 * * *" + + # Create a backup every 6 hours with the @every notation. + velero create schedule NAME --schedule="@every 6h"`, + } + + replaceVeleroWithOADP(cmd) + + if strings.Contains(cmd.Example, "velero create schedule") { + t.Errorf("Expected verb-first 'velero create schedule' to be normalized, got: %s", cmd.Example) + } + if strings.Contains(cmd.Example, "velero") { + t.Errorf("Expected 'velero' to be fully replaced, got: %s", cmd.Example) + } + wantCount := strings.Count(cmd.Example, "oc oadp schedule create NAME") + if wantCount != 2 { + t.Errorf("Expected 2 occurrences of 'oc oadp schedule create NAME', got %d\nActual output:\n%s", wantCount, cmd.Example) + } +} + // TestReplaceVeleroWithOADP_RunFunctionWrapper tests stdout capture and replacement func TestReplaceVeleroWithOADP_RunFunctionWrapper(t *testing.T) { outputCaptured := false