Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,48 @@ func main() {
}
```

### `flagrun.Validator` — 引数の追加検証

`flagrun.Validator` を使うと、コマンドライン引数のパース後に追加の検証を行えます。検証関数は `func([]string) error` のシグネチャを持ち、エラーを返した場合は標準エラー出力にメッセージを出力して `UNKNOWN` で終了します。

```go
package main

import (
"fmt"

"github.com/monitoring-forge/flagrun"
)

type Opt struct {
Host string `short:"H" long:"host" default:"localhost" description:"Target host"`
Port int `short:"p" long:"port" default:"8080" description:"Target port"`
Version bool `short:"v" long:"version" description:"Show version"`
}

func (p *Opt) Run(args []string) (string, int) {
return "ok\t1", flagrun.OK
}

func (p *Opt) Validator(args []string) error {
if p.Port < 1 || p.Port > 65535 {
return fmt.Errorf("port must be between 1 and 65535: %d", p.Port)
}
return nil
}

func main() {
opt := &Opt{}
os.Exit(flagrun.Go(
opt,
flagrun.Version(version),
flagrun.Validator(opt.Validator),
))
}
```

検証は `go-flags` によるパース成功後、`Run` メソッドの呼び出し前に実行されます。`flagrun.Go` / `flagrun.Check` / `flagrun.Ship` のいずれでも利用できます。

## オプション

| `flagrun.Go` / `flagrun.Check` / `flagrun.Ship` では、以下の関数を使って動作をカスタマイズできます。
Expand All @@ -131,6 +173,7 @@ func main() {
| `flagrun.Commit(commit string)` | コミットハッシュなどを指定します(デフォルト: `dev`)。 |
| `flagrun.ArgsRequired()` | コマンドライン引数を必須にします。引数がない場合は UNKNOWN で終了します。 |
| `flagrun.AlwaysStdout()` | `Run` の戻り値を、終了コードに関係なく標準出力へ出力します。`flagrun.Check` では常に標準出力へ出力されるため、このオプションは不要です。 |
| `flagrun.Validator(validator func([]string) error)` | パース後の追加検証を行う関数を指定します。エラー時は UNKNOWN で終了します。 |

## 終了コード

Expand Down
15 changes: 15 additions & 0 deletions flagrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type Flagrun struct {
Version string
Commit string
AlwaysStdout bool
Validator func([]string) error
}

type FlagrunOptions func(*Flagrun)
Expand Down Expand Up @@ -73,6 +74,12 @@ func AlwaysStdout() FlagrunOptions {
}
}

func Validator(validator func([]string) error) FlagrunOptions {
return func(f *Flagrun) {
f.Validator = validator
}
}

func printLine(w io.Writer, s string) error {
if w == nil {
return nil
Expand Down Expand Up @@ -178,6 +185,14 @@ func (f *Flagrun) parseArgs(argv []string, stdout, stderr io.Writer, opt any) ([
psr.WriteHelp(stderr)
return nil, nullint(UNKNOWN)
}

if f.Validator != nil {
if err := f.Validator(args); err != nil {
fmt.Fprintf(stderr, "%v\n", err)
return nil, nullint(UNKNOWN)
}
}

return args, nil
}

Expand Down
20 changes: 20 additions & 0 deletions flagrun_shipper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package flagrun

import (
"bytes"
"fmt"
"os"
"testing"

Expand All @@ -10,13 +11,21 @@ import (

type testShipper struct {
Version bool `short:"v" long:"version" description:"Show version"`
Valid bool `short:"V" long:"valid" description:"Valid parameter"`
ran bool
}

func (s *testShipper) Run(_ []string) {
s.ran = true
}

func (s *testShipper) Validator(_ []string) error {
if !s.Valid {
return fmt.Errorf("Valid parameter is not set")
}
return nil
}

func TestInternalShipper(t *testing.T) {
f := buildFlagrun()
o := &testShipper{}
Expand Down Expand Up @@ -63,3 +72,14 @@ func TestShip(t *testing.T) {
assert.Equal(t, OK, code)
assert.True(t, o.ran)
}

func TestInternalShipperValidator(t *testing.T) {
o := &testShipper{}
f := buildFlagrun(Validator(o.Validator))
var stdout bytes.Buffer
var stderr bytes.Buffer
code := f.internalShipper([]string{}, &stdout, &stderr, o)

assert.Equal(t, UNKNOWN, code)
assert.Contains(t, stderr.String(), "Valid parameter is not set")
}
9 changes: 5 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ module github.com/monitoring-forge/flagrun

go 1.25.0

require github.com/jessevdk/go-flags v1.6.1

require go.yaml.in/yaml/v3 v3.0.5 // indirect

require (
github.com/jessevdk/go-flags v1.6.1
github.com/mackerelio/checkers v0.2.1
github.com/stretchr/testify v1.12.1
)

require (
go.yaml.in/yaml/v3 v3.0.5 // indirect
golang.org/x/sys v0.47.0 // indirect
)