Skip to content

Commit 75b1f2c

Browse files
committed
add compile_registry_state command
1 parent b126a3d commit 75b1f2c

File tree

4 files changed

+198
-1
lines changed

4 files changed

+198
-1
lines changed

docs/howto/script_testing.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ a stack, starting agents and services and validating results.
4949
- agent commands:
5050
- `install_agent [-profile <profile>] [-timeout <duration>] [-container_name <container_name_label>] [-network_name <network_name_label>]`: install an Elastic Agent policy, setting the environment variables named in the container_name and network_name arguments
5151
- `uninstall_agent [-profile <profile>] [-timeout <duration>]`: remove an installed Elastic Agent policy
52+
- `compile_registry_state [-start <first_id_to_use>] <path_to_registry_log>`: compile a Filebeat registry log.json file into a registry state and print it to stdout
5253

5354
- package commands:
5455
- `add_package [-profile <profile>] [-timeout <duration>]`: add the current package's assets

internal/testrunner/script/agents.go

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ package script
66

77
import (
88
"context"
9+
"encoding/json"
910
"errors"
1011
"flag"
1112
"fmt"
12-
"path/filepath"
13+
"io"
14+
"os"
1315
"time"
1416

1517
"github.com/rogpeppe/go-internal/testscript"
@@ -234,3 +236,83 @@ func deletePolicies(ctx context.Context, cli *kibana.Client, a *installedAgent)
234236
}
235237
return errors.Join(errs...)
236238
}
239+
240+
func compileRegistryState(ts *testscript.TestScript, neg bool, args []string) {
241+
if neg {
242+
ts.Fatalf("unsupported: ! get_registry_state")
243+
}
244+
clearStdStreams(ts)
245+
flg := flag.NewFlagSet("uninstall", flag.ContinueOnError)
246+
first := flg.Int64("start", 0, "first registry log operation ID to use")
247+
pretty := flg.Bool("pretty", false, "pretty print the registry")
248+
ts.Check(flg.Parse(args))
249+
if flg.NArg() != 1 {
250+
ts.Fatalf("usage: get_registry_state [-start <first_id_to_use>] <path_to_registry_log>")
251+
}
252+
var choose func(int64) bool
253+
if *first != 0 {
254+
choose = func(i int64) bool {
255+
return i >= *first
256+
}
257+
}
258+
f, err := os.Open(ts.MkAbs(flg.Arg(0)))
259+
defer f.Close()
260+
ts.Check(decoratedWith("opening registry log", err))
261+
262+
s := make(map[string]any)
263+
ts.Check(decoratedWith("compiling state", compileStateInto(s, f, choose)))
264+
var msg []byte
265+
if *pretty {
266+
msg, err = json.MarshalIndent(s, "", " ")
267+
} else {
268+
msg, err = json.Marshal(s)
269+
}
270+
ts.Check(decoratedWith("marshaling registry", err))
271+
fmt.Fprintf(ts.Stdout(), "%s\n", msg)
272+
}
273+
274+
func compileStateInto(dst map[string]any, r io.Reader, choose func(int64) bool) error {
275+
type action struct {
276+
Operation string `json:"op"`
277+
ID int64 `json:"id"`
278+
}
279+
280+
type delta struct {
281+
Key string `json:"K"`
282+
Val map[string]any `json:"V"`
283+
}
284+
285+
dec := json.NewDecoder(r)
286+
dec.DisallowUnknownFields()
287+
for {
288+
var (
289+
a action
290+
d delta
291+
)
292+
err := dec.Decode(&a)
293+
if err != nil {
294+
if err == io.EOF {
295+
return nil
296+
}
297+
return err
298+
}
299+
err = dec.Decode(&d)
300+
if err != nil {
301+
if err == io.EOF {
302+
return io.ErrUnexpectedEOF
303+
}
304+
return err
305+
}
306+
if choose != nil && !choose(a.ID) {
307+
continue
308+
}
309+
switch a.Operation {
310+
case "set":
311+
dst[d.Key] = d.Val
312+
case "remove":
313+
delete(dst, d.Key)
314+
default:
315+
return fmt.Errorf("unknown operation: %q", a.Operation)
316+
}
317+
}
318+
}

internal/testrunner/script/script.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ func Run(dst io.Writer, cmd *cobra.Command, args []string) error {
211211
"dump_logs": dumpLogs,
212212
"match_file": match,
213213
"get_policy": getPolicyCommand,
214+
"compile_registry_state": compileRegistryState,
214215
},
215216
Setup: func(e *testscript.Env) error {
216217
e.Setenv("PROFILE", config.CurrentProfile())
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
compile_registry_state -pretty keys_log.json
2+
cmp stdout want_keys_log_0.json
3+
4+
compile_registry_state -pretty -start=3 keys_log.json
5+
cmp stdout want_keys_log_3.json
6+
7+
compile_registry_state -pretty key_log.json
8+
cmp stdout want_key_log.json
9+
10+
compile_registry_state -pretty keys_removed_log.json
11+
cmp stdout want_keys_removed_log.json
12+
13+
-- keys_log.json --
14+
{"op":"set", "id": 1}
15+
{"K":"key0","V":{"a":0}}
16+
{"op":"set", "id": 2}
17+
{"K":"key1","V":{"a":1}}
18+
{"op":"set", "id": 3}
19+
{"K":"key2","V":{"a":2}}
20+
{"op":"set", "id": 4}
21+
{"K":"key3","V":{"a":3}}
22+
{"op":"set", "id": 5}
23+
{"K":"key4","V":{"a":4}}
24+
{"op":"set", "id": 6}
25+
{"K":"key5","V":{"a":5}}
26+
-- want_keys_log_0.json --
27+
{
28+
"key0": {
29+
"a": 0
30+
},
31+
"key1": {
32+
"a": 1
33+
},
34+
"key2": {
35+
"a": 2
36+
},
37+
"key3": {
38+
"a": 3
39+
},
40+
"key4": {
41+
"a": 4
42+
},
43+
"key5": {
44+
"a": 5
45+
}
46+
}
47+
-- want_keys_log_3.json --
48+
{
49+
"key2": {
50+
"a": 2
51+
},
52+
"key3": {
53+
"a": 3
54+
},
55+
"key4": {
56+
"a": 4
57+
},
58+
"key5": {
59+
"a": 5
60+
}
61+
}
62+
-- key_log.json --
63+
{"op":"set", "id": 1}
64+
{"K":"key0","V":{"a":0}}
65+
{"op":"set", "id": 2}
66+
{"K":"key0","V":{"a":1}}
67+
{"op":"set", "id": 3}
68+
{"K":"key0","V":{"a":2}}
69+
{"op":"set", "id": 4}
70+
{"K":"key0","V":{"a":3}}
71+
{"op":"set", "id": 5}
72+
{"K":"key0","V":{"a":4}}
73+
{"op":"set", "id": 6}
74+
{"K":"key0","V":{"a":5}}
75+
-- want_key_log.json --
76+
{
77+
"key0": {
78+
"a": 5
79+
}
80+
}
81+
-- keys_removed_log.json --
82+
{"op":"set", "id": 1}
83+
{"K":"key0","V":{"a":0}}
84+
{"op":"set", "id": 2}
85+
{"K":"key1","V":{"a":1}}
86+
{"op":"set", "id": 3}
87+
{"K":"key2","V":{"a":2}}
88+
{"op":"set", "id": 4}
89+
{"K":"key3","V":{"a":3}}
90+
{"op":"set", "id": 5}
91+
{"K":"key4","V":{"a":4}}
92+
{"op":"set", "id": 6}
93+
{"K":"key5","V":{"a":5}}
94+
{"op":"remove", "id": 7}
95+
{"K":"key3"}
96+
-- want_keys_removed_log.json --
97+
{
98+
"key0": {
99+
"a": 0
100+
},
101+
"key1": {
102+
"a": 1
103+
},
104+
"key2": {
105+
"a": 2
106+
},
107+
"key4": {
108+
"a": 4
109+
},
110+
"key5": {
111+
"a": 5
112+
}
113+
}

0 commit comments

Comments
 (0)