Skip to content

Commit

Permalink
skip verification if digest empty
Browse files Browse the repository at this point in the history
  • Loading branch information
lesomnus committed Nov 25, 2024
1 parent 786923f commit a1cc501
Show file tree
Hide file tree
Showing 11 changed files with 146 additions and 84 deletions.
14 changes: 12 additions & 2 deletions bringer/smb.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,27 @@ func SmbBringer(opts ...Option) Bringer {

type smbFile struct {
*smb2.File
l *slog.Logger

share *smb2.Share
session *smb2.Session
conn net.Conn
}

func (f *smbFile) Close() error {
return errors.Join(
if f.conn == nil {
return nil
}

f.l.Debug("close SMB file")
err := errors.Join(
f.share.Umount(),
f.session.Logoff(),
f.conn.Close(),
)

f.conn = nil
return err
}

func (b *smbBringer) bring(ctx context.Context, t thing.Thing, opts ...Option) (v *smbFile, err error) {
Expand All @@ -64,7 +74,7 @@ func (b *smbBringer) bring(ctx context.Context, t thing.Thing, opts ...Option) (
c := b.conf
c.apply(opts)

v = &smbFile{}
v = &smbFile{l: l}

host := t.Url.Host
if !strings.Contains(host, ":") {
Expand Down
69 changes: 36 additions & 33 deletions cmd/bring.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/lesomnus/bring/internal/hook"
"github.com/lesomnus/bring/internal/hooks"
"github.com/lesomnus/bring/internal/task"
"github.com/lesomnus/bring/log"
"github.com/lesomnus/bring/thing"
"github.com/urfave/cli/v3"
)
Expand Down Expand Up @@ -47,52 +48,63 @@ func NewCmdBring() *cli.Command {
return fmt.Errorf("expected 1 or 2 arguments")
}

conf := config.From(ctx)
c := config.From(ctx)
if dest != "" {
conf.Dest = dest
c.Dest = dest
}
if conf.Dest == "" {
if c.Dest == "" {
return fmt.Errorf("destination must be specified in the config file or given by argument")
}

var err error
executor.Secret, err = conf.Secret.Open(ctx)
if err != nil {
if s, err := c.Secret.Open(ctx); err != nil {
return fmt.Errorf("open secret store: %w", err)
} else {
executor.Secret = s
}

num_errors := 0
executor.NewHook = func(ctx context.Context, t task.Task) hook.Hook {
return hook.Tie(
&sinkHookMw{D: t.Dest},
hook.Forward(
hook.Join(
&countErrHook{n: &num_errors},
&hooks.PrintHook{T: t, O: os.Stdout},
),
),
hook.Forward(hook.Join(
&hooks.LogHook{T: t, L: log.From(ctx)},
&hooks.PrintHook{T: t, O: os.Stdout},
)),
)
}

job := task.Job{
NumTasks: conf.Things.Len(),
}
i := 0
conf.Things.Walk(conf.Dest, func(p string, t *thing.Thing) {
num_tasks := c.Things.Len()
num_tasks_done := 0
num_errors := 0
err := c.Things.Walk(c.Dest, func(p string, t *thing.Thing) error {
task := task.Task{
Thing: *t,

BringConfig: conf.Each,
BringConfig: c.Each,

Job: job,
Order: i,
Job: task.Job{NumTasks: num_tasks},
Order: num_tasks_done,
Dest: p,
}

executor.Execute(ctx, task)
i++
})
if err := c.Secret.OpenTo(ctx, t.Url, &executor.Secret); err != nil {
return err
}

ctx, cancel := c.Each.ApplyBringTimeout(ctx)
defer cancel()

if r, err := executor.Execute(ctx, task); err != nil {
num_errors++
} else if r != nil {
defer r.Close()
}
num_tasks_done++

return nil
})
if err != nil {
return err
}
if num_errors > 0 {
return cli.Exit("failed to bring some of things", 1)
}
Expand Down Expand Up @@ -133,12 +145,3 @@ func (h *sinkHookMw) OnDone(next hook.Hook, r io.Reader) {
next.OnDone(r)
}
}

type countErrHook struct {
hook.NopHook
n *int
}

func (h *countErrHook) OnError(err error) {
*h.n++
}
36 changes: 27 additions & 9 deletions cmd/digest.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import (
"fmt"
"net/url"

"github.com/lesomnus/bring/bringer"
"github.com/lesomnus/bring/config"
"github.com/lesomnus/bring/internal/hook"
"github.com/lesomnus/bring/internal/hooks"
"github.com/lesomnus/bring/internal/task"
"github.com/lesomnus/bring/log"
"github.com/lesomnus/bring/thing"
"github.com/opencontainers/go-digest"
"github.com/urfave/cli/v3"
Expand Down Expand Up @@ -46,22 +50,36 @@ func NewCmdDigest() *cli.Command {

var u url.URL
if v, err := url.Parse(target); err != nil {
return fmt.Errorf("parse target: %w", err)
return fmt.Errorf("parse resource URL: %w", err)
} else {
u = *v
}

b, err := bringer.FromUrl(u)
if err != nil {
return fmt.Errorf("get bringer: %w", err)
c := config.From(ctx)
l := log.From(ctx)
executor := &executor{
DryRun: true,
NewHook: func(ctx context.Context, t task.Task) hook.Hook {
return &hooks.LogHook{T: t, L: l}
},
}
if err := c.Secret.OpenTo(ctx, u, &executor.Secret); err != nil {
return err
}

t := thing.Thing{Url: u}
r, err := b.Bring(ctx, t)
ctx, cancel := c.Each.ApplyBringTimeout(ctx)
defer cancel()

r, err := executor.Execute(ctx, task.Task{
Thing: thing.Thing{Url: u},

BringConfig: c.Each,
})
if err != nil {
return fmt.Errorf("get reader: %w", err)
return err
} else {
defer r.Close()
}
defer r.Close()

d, err := algorithm.FromReader(r)
if err != nil {
Expand Down
63 changes: 36 additions & 27 deletions cmd/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,62 +21,71 @@ type executor struct {
NewHook func(ctx context.Context, t task.Task) hook.Hook
}

func (e *executor) Execute(ctx context.Context, t task.Task) {
func (e *executor) secret() secret.Store {
if e.Secret != nil {
return e.Secret
}

return secret.NopStore()
}

func (e *executor) Execute(ctx context.Context, t task.Task) (io.ReadCloser, error) {
hook := e.NewHook(ctx, t)
hook.OnStart()
defer hook.OnFinish()

with_validate := !(t.Dest == "" || t.Thing.Digest == "")

if err := t.Thing.Validate(); err != nil {
hook.OnError(fmt.Errorf("invalid thing: %w", err))
return
err = fmt.Errorf("invalid thing: %w", err)
hook.OnError(err)
return nil, err
}

b, err := bringer.FromUrl(t.Thing.Url)
if err != nil {
hook.OnError(fmt.Errorf("get bringer: %w", err))
return
} else {
err = fmt.Errorf("get bringer: %w", err)
hook.OnError(err)
return nil, err
} else if with_validate {
b = bringer.SafeBringer(b)
}

if ok, err := e.validate(t.Dest, t.Thing.Digest); err != nil {
hook.OnError(err)
return
} else if ok {
// Digest matches, skips bringing.
hook.OnSkip()
return
if with_validate {
if ok, err := e.validate(t.Dest, t.Thing.Digest); err != nil {
hook.OnError(err)
return nil, err
} else if ok {
// Digest matches, skips bringing.
hook.OnSkip()
return nil, nil
}
}

opts := []bringer.Option{}
opts = append(opts, t.BringConfig.AsOpts()...)
if pw, err := e.Secret.Read(ctx, t.Thing.Url); err != nil && !errors.Is(err, os.ErrNotExist) {
hook.OnError(fmt.Errorf("read secret: %w", err))
return
if pw, err := e.secret().Read(ctx, t.Thing.Url); err != nil && !errors.Is(err, os.ErrNotExist) {
err = fmt.Errorf("read secret: %w", err)
hook.OnError(err)
return nil, err
} else {
opts = append(opts, bringer.WithPassword(string(pw)))
}
if t.BringConfig.DialTimeout != 0 {
opts = append(opts, bringer.WithDialTimeout(t.BringConfig.DialTimeout))
}

ctx, cancel := t.BringConfig.ApplyTimeout(ctx)
defer cancel()

r, err := b.Bring(ctx, t.Thing, opts...)
if err != nil {
hook.OnError(fmt.Errorf("bring: %w", err))
return
} else {
defer r.Close()
err := fmt.Errorf("bring: %w", err)
hook.OnError(err)
return nil, err
}

if e.DryRun {
hook.OnDone(nil)
return
return r, nil
}

hook.OnDone(r)
return r, nil
}

func (e *executor) validate(p string, d digest.Digest) (bool, error) {
Expand Down
2 changes: 1 addition & 1 deletion config/bring.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type BringConfig struct {
DialTimeout time.Duration `yaml:"dial_timeout"`
}

func (c *BringConfig) ApplyTimeout(ctx context.Context) (context.Context, context.CancelFunc) {
func (c *BringConfig) ApplyBringTimeout(ctx context.Context) (context.Context, context.CancelFunc) {
if c.BringTimeout == 0 {
return ctx, func() {}
}
Expand Down
15 changes: 9 additions & 6 deletions config/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type Entry struct {
Thing *thing.Thing
}

type EntryWalkFunc func(p string, t *thing.Thing)
type EntryWalkFunc func(p string, t *thing.Thing) error

func (e *Entry) IsLeaf() bool {
return e != nil && e.Thing != nil
Expand All @@ -35,20 +35,23 @@ func (e *Entry) Len() int {
return l
}

func (e *Entry) Walk(p string, f EntryWalkFunc) {
func (e *Entry) Walk(p string, f EntryWalkFunc) error {
if e.IsLeaf() {
f(p, e.Thing)
return
return f(p, e.Thing)
}
if e.Next == nil {
return
return nil
}

ks := maps.Keys(e.Next)
for _, k := range slices.Sorted(ks) {
p := filepath.Join(p, k)
e.Next[k].Walk(p, f)
if err := e.Next[k].Walk(p, f); err != nil {
return err
}
}

return nil
}

func (e *Entry) UnmarshalYAML(n *yaml.Node) error {
Expand Down
3 changes: 2 additions & 1 deletion config/entry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@ a:
require.NoError(err)

visited := []string{}
root.Walk("", func(p string, t *thing.Thing) {
root.Walk("", func(p string, t *thing.Thing) error {
visited = append(visited, p)
return nil
})
require.Equal(
visited,
Expand Down
17 changes: 17 additions & 0 deletions config/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,23 @@ func (c *SecretConfig) Open(ctx context.Context) (secret.Store, error) {
return secret.FromUrl(ctx, u)
}

func (c *SecretConfig) OpenTo(ctx context.Context, u url.URL, store *secret.Store) error {
if *store != nil {
return nil
}
if u.User.Username() == "" {
return nil
}

s, err := c.Open(ctx)
if err != nil {
return fmt.Errorf("open secret store: %w", err)
}

*store = s
return nil
}

func (c *SecretConfig) AsOpts(ctx context.Context, store secret.Store, u url.URL) ([]bringer.Option, error) {
if u.User.Username() == "" {
return nil, nil
Expand Down
3 changes: 1 addition & 2 deletions internal/hooks/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import (

type LogHook struct {
T task.Task
L slog.Logger
N int // Number of tasks.
L *slog.Logger
}

func (h *LogHook) OnStart() {
Expand Down
Loading

0 comments on commit a1cc501

Please sign in to comment.