...
1 package sink_test
2
3 import (
4 "bytes"
5 "context"
6 "fmt"
7 "os"
8 "os/signal"
9
10 "edge-infra.dev/pkg/lib/cli/rags"
11 "edge-infra.dev/pkg/lib/cli/sink"
12 )
13
14 type client struct {
15 user string
16 password string
17 endpoint string
18 }
19
20 func (c client) ping() bool {
21 return true
22 }
23
24
25
26
27 type cliExt struct {
28 client client
29 }
30
31
32 func (c *cliExt) RegisterFlags(rs *rags.RagSet) {
33 rs.StringVar(&c.client.user, "user", "tom", "service user")
34 rs.StringVar(&c.client.password, "password", "hunter22", "trust me")
35 rs.StringVar(&c.client.endpoint, "endpoint", "https://ncr.com", "the point where you end")
36 }
37
38
39
40 func (c *cliExt) BeforeRun(ctx context.Context, r sink.Run) (context.Context, sink.Run, error) {
41 r.Log = r.Log.
42 WithName(r.Cmd().Name()).
43 WithValues("endpoint", c.client.endpoint)
44
45
46 if !c.client.ping() {
47 return ctx, r, fmt.Errorf("failed to instantiate client")
48 }
49 r.Log.WithName("before").Info("instantiated client")
50
51 return ctx, r, nil
52 }
53
54 func NewCmd() *sink.Command {
55 var (
56 force bool
57 e = &cliExt{}
58 )
59
60 cmd := &sink.Command{
61 Use: "client-user [flags] <operation>",
62 Extensions: []sink.Extension{e},
63 Flags: []*rags.Rag{
64 {
65 Name: "force",
66 Usage: "Force operation in case of conflict",
67 Value: &rags.Bool{Var: &force},
68 },
69 },
70 Exec: func(_ context.Context, r sink.Run) error {
71
72
73 if !e.client.ping() && !force {
74 return fmt.Errorf("operation failed, try again with --force")
75 }
76
77 r.Log.Info("successfully hit service")
78 return nil
79 },
80 }
81
82
83
84 cmd.SetOut(os.Stdout)
85 cmd.SetErr(os.Stdout)
86
87 return cmd
88 }
89
90 func ExampleCommand_ParseAndRun() {
91
92 cmd := NewCmd()
93
94 ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
95 defer cancel()
96 if err := cmd.ParseAndRun(ctx, []string{}); err != nil {
97 cancel()
98 os.Exit(1)
99 }
100
101
102
103 }
104
105 func ExampleCommand_Parse() {
106
107
108 cmd := NewCmd()
109 if err := cmd.Parse([]string{}); err != nil {
110 fmt.Fprintln(os.Stderr, err.Error())
111 }
112
113 ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
114 defer cancel()
115 if err := cmd.Run(ctx); err != nil {
116 cancel()
117 os.Exit(1)
118 }
119
120
121
122 }
123
124 func ExampleCommand_output() {
125 cmd := &sink.Command{
126 Use: "fetcher",
127 Short: "Fetch data from a remote service",
128 Exec: func(_ context.Context, r sink.Run) error {
129 log := r.Log.WithName("fetcher")
130
131
132 log.Info("fetching data")
133 data := fetchData()
134
135
136 fmt.Fprintln(r.Out(), data)
137 log.Info("data fetched")
138 return nil
139 },
140 }
141
142
143 errWriter := new(bytes.Buffer)
144 cmd.SetErr(errWriter)
145 outWriter := new(bytes.Buffer)
146 cmd.SetOut(outWriter)
147
148 if err := cmd.ParseAndRun(context.Background(), []string{}); err != nil {
149 os.Exit(1)
150 }
151
152 fmt.Println("standard out:", outWriter.String())
153 fmt.Println("standard error:", errWriter.String())
154
155
156
157
158
159 }
160
161 func fetchData() string {
162 return "this data is going to come over stdout for consumption by other programs"
163 }
164
View as plain text