Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a7e2329
[#1587] Exclude a common part of CLI parser
fivitti Jan 2, 2025
ac04f65
[#1587] Working general CLI parser
fivitti Jan 3, 2025
ffd2cf4
[#1587] Fix the wrong argument
fivitti Jan 7, 2025
8808118
[#1587] Unify agent and server parsers
fivitti Jan 7, 2025
e301a43
[#1587] Verify the envvars
fivitti Jan 7, 2025
30c4d21
[#1587] Fix linter issues
fivitti Jan 7, 2025
c8ca1c5
[#1587] Verify system environment variables
fivitti Jan 7, 2025
81b857a
[#1587] Add unit tests
fivitti Jan 7, 2025
48add73
[#1587] Extend unit test
fivitti Jan 7, 2025
06ba0b6
[#1587] Fix unit tests
fivitti Jan 7, 2025
cfb6ec4
[#1587] Simplify utility
fivitti Jan 7, 2025
7a29eb8
[#1587] Fix linter issue
fivitti Jan 8, 2025
522be1b
[#1587] Remove redundant flags
fivitti Jan 8, 2025
c6657d4
[#1587] Add unit tests
fivitti Jan 8, 2025
bf98f00
[#1587] Add a Changelog entry
fivitti Jan 8, 2025
19b7c94
[#1587] Unify the CLI handling in the Stork tool
fivitti Jan 8, 2025
66db02f
[#1587] Move package
fivitti Jan 8, 2025
425910d
[#1587] Exclude app to a separate file
fivitti Jan 8, 2025
7b201bd
[#1587] Unexport structs
fivitti Jan 8, 2025
6569020
[#1587] Unify code-gen CLI
fivitti Jan 8, 2025
27c6b7c
[#1587] Remove unnecessary dependencies
fivitti Jan 8, 2025
185123d
[#1587] Rename structs
fivitti Jan 9, 2025
f1d16f2
[#1587] Add unit tests
fivitti Jan 9, 2025
60f2fe4
[#1587] Rephrase a sentence
fivitti Jan 9, 2025
1acfd8d
[#1587] Support hooks only for agent and server
fivitti Jan 9, 2025
9285a3c
[#1587] Add unit test
fivitti Jan 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[#1587] Support hooks only for agent and server
  • Loading branch information
fivitti authored and tomaszmrugalski committed Jun 2, 2025
commit 1acfd8dfe206592a972afdb92a726991e5b039a7
4 changes: 2 additions & 2 deletions backend/cli/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ func (a *App) RegisterCommand(command, shortDescription string, data command, ac

// Starts the application with the provided arguments.
// Run requested subcommand or show help or version.
func (a *App) Run(args []string) error {
func (a *App) Run(application string, args []string) error {
// Parse command line arguments.
appParser := NewCLIParser(a.parser, "tool", func() {
appParser := NewCLIParser(a.parser, application, func() {
storkutil.SetupLogging()
})

Expand Down
63 changes: 52 additions & 11 deletions backend/cli/app_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cli

import (
"fmt"
"strings"
"testing"

Expand Down Expand Up @@ -31,18 +32,58 @@ func TestRunVersion(t *testing.T) {
// Arrange
parser := flags.NewParser(&struct{}{}, flags.Default)
app := NewApp(parser)
var err error

for _, arg := range []string{"-v", "--version"} {
// Act
stdout, _, _ := testutil.CaptureOutput(func() {
err = app.Run([]string{arg})
t.Run(arg, func(t *testing.T) {
var err error

// Act
stdout, _, _ := testutil.CaptureOutput(func() {
err = app.Run("agent", []string{arg})
})

// Assert
require.NoError(t, err)
require.True(t, app.showVersion)
require.Equal(t, stork.Version, strings.TrimSpace(string(stdout)))
})
}
}

// Assert
require.NoError(t, err)
require.True(t, app.showVersion)
require.Equal(t, stork.Version, strings.TrimSpace(string(stdout)))
// Test that the help printing is handled internally.
// Check if the hook directory is shown for agent and server.
func TestRunHelp(t *testing.T) {
// Arrange
for _, name := range []string{"tool", "agent", "server", "code-gen", "unknown"} {
for _, arg := range []string{"-h", "--help"} {
parser := flags.NewParser(&struct{}{}, flags.Default)
parser.Name = "foo"
parser.ShortDescription = "Bar"
parser.LongDescription = "Baz"
app := NewApp(parser)

t.Run(fmt.Sprintf("%s/%s", name, arg), func(t *testing.T) {
// Act
var err error
stdout, _, _ := testutil.CaptureOutput(func() {
err = app.Run(name, []string{arg})
})

// Assert
require.NoError(t, err)
require.Contains(t, string(stdout), "foo")
require.NotContains(t, string(stdout), "Bar")
require.Contains(t, string(stdout), "Baz")
require.Contains(t, string(stdout), "--help")
require.Contains(t, string(stdout), "--version")

if name == "agent" || name == "server" {
require.Contains(t, string(stdout), "--hook-directory")
} else {
require.NotContains(t, string(stdout), "--hook-directory")
}
})
}
}
}

Expand All @@ -53,7 +94,7 @@ func TestRunNoCommand(t *testing.T) {
app := NewApp(parser)

// Act
err := app.Run([]string{})
err := app.Run("server", []string{})

// Assert
require.ErrorContains(t, err, "no command specified")
Expand All @@ -67,7 +108,7 @@ func TestRunUnknownCommand(t *testing.T) {
app := NewApp(parser)

// Act
err := app.Run([]string{"unknown"})
err := app.Run("agent", []string{"unknown"})

// Assert
require.ErrorContains(t, err, "no command specified")
Expand All @@ -90,7 +131,7 @@ func TestRunCommand(t *testing.T) {
app.RegisterCommand("bar", "Bar", data, func() {
isCalled = true
})
err := app.Run([]string{"bar", "-f", "baz"})
err := app.Run("tool", []string{"bar", "-f", "baz"})

// Assert
require.NoError(t, err)
Expand Down
54 changes: 26 additions & 28 deletions backend/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,11 @@ type CLIParser struct {
// Accepts the main parser. It should be configured with the application
// settings.
// The application name is used to construct the namespaces for the CLI flags
// and environment variables. It should be either 'server', 'agent', 'tool'.
// and environment variables.
// The callback is called when the environment file is loaded. Its purpose is
// to allow reconfiguring the logging using the new environment variables as
// soon as they are available.
func NewCLIParser(parser *flags.Parser, app string, onLoadEnvironmentFileCallback func()) *CLIParser {
if app != "server" && app != "agent" && app != "tool" {
// Programming error.
panic("invalid application name")
}

return &CLIParser{
parser: parser,
application: strings.ToLower(app),
Expand Down Expand Up @@ -110,36 +105,41 @@ func (p *CLIParser) bootstrap(args []string) (*HookDirectorySettings, GroupedHoo
}

// Process the hook directory location.
hookDirectorySettings := &HookDirectorySettings{}
hookParser := p.createSubParser(hookDirectorySettings)
if _, err := hookParser.ParseArgs(args); err != nil {
return nil, nil, err
}
var hookDirectorySettings *HookDirectorySettings
var allHookCLIFlags GroupedHookCLIFlags
if p.application == "server" || p.application == "agent" {
hookDirectorySettings = &HookDirectorySettings{}
hookParser := p.createSubParser(hookDirectorySettings)
if _, err := hookParser.ParseArgs(args); err != nil {
return nil, nil, err
}

allHookCLIFlags, err := p.collectHookCLIFlags(hookDirectorySettings)
if err != nil {
return nil, nil, err
}
err = p.mergeHookFlags(allHookCLIFlags)
if err != nil {
return nil, nil, err
allHookCLIFlags, err = p.collectHookCLIFlags(hookDirectorySettings)
if err != nil {
return nil, nil, err
}
err = p.mergeHookFlags(allHookCLIFlags)
if err != nil {
return nil, nil, err
}

// Append the hook directory-related flags to the main parser.
group, err := p.parser.AddGroup("Hook Directory Flags", "", hookDirectorySettings)
if err != nil {
err = errors.Wrap(err, "cannot add the hook directory group")
return nil, nil, err
}
p.substitutePlaceholdersInGroup(group)
}

// Append the parser-related flags to the main parser.
// Append the environment file-related flags to the main parser.
group, err := p.parser.AddGroup("Environment File Flags", "", envFileSettings)
if err != nil {
err = errors.Wrap(err, "cannot add the environment file group")
return nil, nil, err
}
p.substitutePlaceholdersInGroup(group)

group, err = p.parser.AddGroup("Hook Directory Flags", "", hookDirectorySettings)
if err != nil {
err = errors.Wrap(err, "cannot add the hook directory group")
return nil, nil, err
}
p.substitutePlaceholdersInGroup(group)

// Verify the environment variables.
err = p.verifyEnvironmentFile(envFileSettings)
if err != nil {
Expand Down Expand Up @@ -392,8 +392,6 @@ func (p *CLIParser) collectHookCLIFlags(hookDirectorySettings *HookDirectorySett
program = hooks.HookProgramServer
case "agent":
program = hooks.HookProgramAgent
case "tool":
program = hooks.HookProgramTool
default:
// Programming error.
return nil, errors.Errorf("unknown application name: %s", p.application)
Expand Down
10 changes: 5 additions & 5 deletions backend/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,17 +406,17 @@ Application Options:
Hook 'baz' Flags:
--baz.foo-bar= Lorem ipsum [$STORK_SERVER_HOOK_BAZ_FOO_BAR]

Hook Directory Flags:
--hook-directory= The path to the hook directory (default:
/usr/lib/stork-server/hooks)
[$STORK_SERVER_HOOK_DIRECTORY]

Environment File Flags:
--env-file= Environment file location; applicable only if the
use-env-file is provided (default:
/etc/stork/server.env)
--use-env-file Read the environment variables from the environment file

Hook Directory Flags:
--hook-directory= The path to the hook directory (default:
/usr/lib/stork-server/hooks)
[$STORK_SERVER_HOOK_DIRECTORY]

Help Options:
-h, --help Show this help message

Expand Down
5 changes: 3 additions & 2 deletions backend/cmd/stork-code-gen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ func generateStdOptionDefs(settings *stdOptionDefinitionsSettings) error {
func main() {
nothing := struct{}{}
parser := flags.NewParser(&nothing, flags.Default)
parser.Name = "Stork Code Gen"
parser.Name = "stork-code-gen"
parser.ShortDescription = "Code generator used in Stork development"
parser.Usage = "stork-code-gen [command] [options]"

app := cli.NewApp(parser)

stdOptionDefinitionsSettings := &stdOptionDefinitionsSettings{}
app.RegisterCommand(
"std-option-defs",
Expand All @@ -49,7 +50,7 @@ func main() {
},
)

err := app.Run(os.Args[1:])
err := app.Run("code-gen", os.Args[1:])
if err != nil {
fmt.Println(err)
os.Exit(1)
Expand Down
4 changes: 2 additions & 2 deletions backend/cmd/stork-tool/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ func newApp() *cli.App {
nothing := struct{}{}
parser := flags.NewParser(&nothing, flags.Default)

parser.Name = "Stork Tool"
parser.Name = "stork-tool"
parser.SubcommandsOptional = true
parser.ShortDescription = "A tool for managing Stork Server."
parser.LongDescription = `The tool operates in four areas:
Expand Down Expand Up @@ -562,7 +562,7 @@ func main() {
storkutil.SetupLogging()

app := newApp()
err := app.Run(os.Args[1:])
err := app.Run("tool", os.Args[1:])
if err != nil {
log.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion backend/cmd/stork-tool/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func TestVersionStandalone(t *testing.T) {
// Act
var err error
stdout, _, captureErr := testutil.CaptureOutput(func() {
err = app.Run(args)
err = app.Run("tool", args)
})

// Assert
Expand Down
2 changes: 0 additions & 2 deletions backend/hooks/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ const (
HookProgramAgent = "Stork Agent"
// Identifier of the Stork Server program.
HookProgramServer = "Stork Server"
// Identifier of the Stork Tool program.
HookProgramTool = "Stork Tool"
)

// The current Stork version. Forwarded from the top Stork package.
Expand Down