Skip to content

Commit

Permalink
😱 trace: patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
rjeczalik committed Jun 29, 2024
1 parent cfd58e4 commit 77c884b
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 41 deletions.
1 change: 1 addition & 0 deletions cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package cmd // import "hookt.dev/cmd"
57 changes: 44 additions & 13 deletions pkg/proto/pattern.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ package proto

import (
"context"
"fmt"
"log/slog"
"text/template"

"hookt.dev/cmd/pkg/errors"
"hookt.dev/cmd/pkg/proto/wire"
"hookt.dev/cmd/pkg/trace"

"github.com/google/go-cmp/cmp"
"github.com/itchyny/gojq"
Expand Down Expand Up @@ -41,34 +44,62 @@ func (p Pattern) Match(ctx context.Context, obj any) (bool, error) {
}

func (p *P) Pattern(ctx context.Context, obj wire.Object) (Pattern, error) {
pt := make(Pattern)
var (
pt = make(Pattern)
tr = trace.ContextPattern(ctx)
err error
)

for k, raw := range obj {
q, err := gojq.Parse(k)
if err != nil {
return nil, errors.New("failed to parse jq %q: %w", k, err)
q, e := gojq.Parse(k)
tr.ParseKey(k, q, e)
if e != nil {
err = errors.Join(
err,
errors.New("failed to parse jq %q: %w", k, e),
)
continue
}

var v any
var want any

if err := yaml.Unmarshal(raw, &v); err != nil {
return nil, errors.New("failed to parse value for jq %q: %w", k, err)
e = yaml.Unmarshal(raw, &want)
tr.UnmarshalValue(k, raw, want, e)
if e != nil {
err = errors.Join(
err,
errors.New("failed to parse value for jq %q: %w", k, e),
)
continue
}

slog.Debug("building pattern",
"key", k,
"pattern", v,
"pattern", want,
)

switch v := v.(type) {
switch want := want.(type) {
case bool:
pt[q] = func(_ context.Context, x any) (bool, error) { return v || x == nil, nil }
pt[q] = func(_ context.Context, got any) (bool, error) { return want || got == nil, nil }
case string:
pt[q] = p.t.Match(ctx, v)
tv := tr.TemplateValue
tr.TemplateValue = func(_, v string, t *template.Template, e error) { tv(k, v, t, e) }
pt[q] = p.t.Match(trace.WithPattern(ctx, tr), want)
default:
pt[q] = func(_ context.Context, x any) (bool, error) { return cmp.Equal(x, v), nil }
pt[q] = func(_ context.Context, got any) (bool, error) {
ok := cmpEqual(want, got)
tr.EqualMatch(k, want, got, ok)
return ok, nil
}
}
}

return pt, nil
return pt, err
}

func cmpEqual(want, got any) bool {
if fmt.Sprint(want) == fmt.Sprint(got) {
return true
}
return cmp.Equal(want, got)
}
9 changes: 6 additions & 3 deletions pkg/proto/pattern_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package proto_test

import (
"context"
"strconv"
"testing"

"hookt.dev/cmd/pkg/proto/wire"
"hookt.dev/cmd/pkg/trace"
)

func TestPattern(t *testing.T) {
Expand Down Expand Up @@ -74,7 +76,7 @@ func TestPattern(t *testing.T) {
},
5: {
wire.Object{
".foo.bar": []byte(`"${{ setvar "bar" . }}"`),
".foo.bar": []byte(strconv.Quote(`${{ setvar "bar" . }}`)),
},
map[string]any{
"foo": map[string]any{
Expand All @@ -85,7 +87,7 @@ func TestPattern(t *testing.T) {
},
6: {
wire.Object{
".foo.bar": []byte(`"${{ var "bar" }}"`),
".foo.bar": []byte(strconv.Quote(`${{ var "bar" }}`)),
},
map[string]any{
"foo": map[string]any{
Expand Down Expand Up @@ -136,6 +138,7 @@ func TestPattern(t *testing.T) {

p := newP()
ctx := context.Background()
ctx = trace.WithPattern(ctx, trace.LogPattern())

for _, cas := range cases {
t.Run("", func(t *testing.T) {
Expand All @@ -146,7 +149,7 @@ func TestPattern(t *testing.T) {

ok, err := pt.Match(ctx, cas.obj)
if err != nil {
t.Fatal(err)
t.Fatalf("match: Match()=%+v", err)
}

if ok != cas.ok {
Expand Down
2 changes: 1 addition & 1 deletion pkg/proto/proto.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (p *P) Parse(ctx context.Context, q []byte) (*Workflow, error) {

var (
w Workflow
tr = trace.ContextJobTrace(ctx)
tr = trace.ContextJob(ctx)
)

w.Jobs = make([]Job, len(raw.Jobs))
Expand Down
21 changes: 19 additions & 2 deletions pkg/proto/proto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,29 @@ package proto_test
import (
"context"
"io/ioutil"
"log/slog"
"os"
"testing"
"time"

"hookt.dev/cmd/pkg/plugin/builtin"
"hookt.dev/cmd/pkg/proto"

"github.com/davecgh/go-spew/spew"
"github.com/lmittmann/tint"
)

func init() {
slog.SetDefault(
slog.New(
tint.NewHandler(os.Stderr, &tint.Options{
AddSource: true,
Level: slog.LevelDebug,
TimeFormat: time.Kitchen,
}),
),
)
}

func newP() *proto.P {
p := builtin.Plugins()
q := make([]proto.Interface, len(p))
Expand All @@ -32,7 +47,9 @@ func TestParse(t *testing.T) {
t.Fatal(err)
}

spew.Dump(w)
_ = w

// spew.Dump(w)
}

func file(t *testing.T, path string) []byte {
Expand Down
31 changes: 21 additions & 10 deletions pkg/proto/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import (

"hookt.dev/cmd/pkg/async"
"hookt.dev/cmd/pkg/errors"
"hookt.dev/cmd/pkg/trace"

"github.com/Masterminds/sprig"
"github.com/google/go-cmp/cmp"
"sigs.k8s.io/yaml"
)

Expand Down Expand Up @@ -64,28 +64,39 @@ func (t *T) funcs() template.FuncMap {
}

func (t *T) Match(ctx context.Context, data string) func(context.Context, any) (bool, error) {
tr := trace.ContextPattern(ctx)
tmpl, err := t.Parse("", data)
tr.TemplateValue("", data, tmpl, err)
if err != nil {
return func(context.Context, any) (bool, error) { return false, err }
}
return func(_ context.Context, x any) (bool, error) {
var buf bytes.Buffer

if err := tmpl.Execute(&buf, x); err != nil {
return func(ctx context.Context, got any) (bool, error) {
var (
buf bytes.Buffer
tr = trace.ContextPattern(ctx)
)

err := tmpl.Execute(&buf, got)
tr.ExecuteMatch("", buf.Bytes(), err)
if err != nil {
return false, errors.New("failed to evaluate %q: %w", data, err)
}

var v any
var want any

if err := yaml.Unmarshal(buf.Bytes(), &v); err != nil {
err = yaml.Unmarshal(buf.Bytes(), &want)
tr.UnmarshalMatch("", buf.Bytes(), want, err)
if err != nil {
return false, errors.New("failed to parse result: %w", err)
}

switch v := v.(type) {
switch want := want.(type) {
case bool:
return v, nil
return want, nil
default:
return cmp.Equal(x, v), nil
ok := cmpEqual(want, got)
tr.EqualMatch("", want, got, ok)
return ok, nil
}
}
}
Expand Down
Loading

0 comments on commit 77c884b

Please sign in to comment.