From 4e046d172c87128d964c54ea8fdf20a3c4118ff9 Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Sun, 2 Apr 2023 23:13:04 -0400 Subject: [PATCH 01/16] add support for entrypoint and default args along the way, remove Thunk.Cmd and instead just use args NOTE: a few things will likely be broken on top of this. --- bass/bass.lock | 841 ------------------------- demos/bass.lock | 248 -------- docs/go/bass.go | 12 +- pkg/bass/cache_path.go | 4 +- pkg/bass/encoding_test.go | 67 +- pkg/bass/enums_test.go | 42 +- pkg/bass/fspath.go | 4 +- pkg/bass/ground.go | 21 +- pkg/bass/ground_test.go | 12 +- pkg/bass/host_path.go | 4 +- pkg/bass/memo_test.go | 8 +- pkg/bass/path.go | 14 +- pkg/bass/proto.go | 12 +- pkg/bass/session.go | 60 +- pkg/bass/session_test.go | 8 +- pkg/bass/thunk.go | 83 ++- pkg/bass/thunk_path.go | 4 +- pkg/bass/thunk_path_test.go | 20 +- pkg/bass/thunk_test.go | 6 +- pkg/bass/thunk_types.go | 225 ------- pkg/bass/value_test.go | 10 +- pkg/cli/run.go | 6 +- pkg/proto/bass.pb.go | 551 ++++++---------- pkg/proto/value.go | 2 + pkg/runtimes/buildkit.go | 263 +++++--- pkg/runtimes/command.go | 19 +- pkg/runtimes/command_test.go | 43 +- pkg/runtimes/suite.go | 13 + pkg/runtimes/testdata/bass.lock | 264 -------- pkg/runtimes/testdata/entrypoints.bass | 26 + proto/bass.proto | 13 +- std/root.bass | 3 +- std/run.bass | 12 +- 33 files changed, 645 insertions(+), 2275 deletions(-) delete mode 100644 bass/bass.lock delete mode 100644 demos/bass.lock delete mode 100644 pkg/runtimes/testdata/bass.lock create mode 100644 pkg/runtimes/testdata/entrypoints.bass diff --git a/bass/bass.lock b/bass/bass.lock deleted file mode 100644 index 6ce7098f..00000000 --- a/bass/bass.lock +++ /dev/null @@ -1,841 +0,0 @@ -memos: { - module: { - cmd: { - command: { - name: "run" - } - } - } - calls: { - binding: "resolve" - results: { - input: { - array: { - values: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine/git" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - } - } - } - } - output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine/git" - } - } - } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:7b9c96bea8268579e925b17170ae208788e90d508ec334421384913ba61cd610" - } - } - } - } - } - } - results: { - input: { - array: { - values: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "ubuntu" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - } - } - } - } - output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "ubuntu" - } - } - } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:20fa2d7bb4de7723f542be5923b06c4d704370f0390e4ae9e1c833c8785644c1" - } - } - } - } - } - } - results: { - input: { - array: { - values: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - } - } - } - } - output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine" - } - } - } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1243f395ee852a8d9730fc2ad" - } - } - } - } - } - } - results: { - input: { - array: { - values: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "moby/buildkit" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "v0.10.3" - } - } - } - } - } - } - } - output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "moby/buildkit" - } - } - } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "v0.10.3" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:0dc312b04eac1b44cd2cad566deb1e886c753109208affbbec8384f381ff7f38" - } - } - } - } - } - } - results: { - input: { - array: { - values: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "vito/buildkit" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "v0.10.3-conflist" - } - } - } - } - } - } - } - output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "vito/buildkit" - } - } - } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "v0.10.3-conflist" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:9e16d0d919f6c2bcba152fd4b02bee3a9a38b2e973e104789753101d8f58d655" - } - } - } - } - } - } - results: { - input: { - array: { - values: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "squareup/certstrap" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - } - } - } - } - output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "squareup/certstrap" - } - } - } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:d620d824b5e6c3e6d318020ab698e5224b83cfdd2338f15113c4596047065ae4" - } - } - } - } - } - } - } -} -memos: { - module: { - cmd: { - command: { - name: "git" - } - } - stdin: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine/git" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:5dbc7ef3c51fd64e996c3ca819d625ca21bbc4259be166fd9a46395d5f6c6a1f" - } - } - } - } - } - } - calls: { - binding: "ls-remote" - results: { - input: { - array: { - values: { - string: { - value: "https://github.com/vito/tabs" - } - } - values: { - string: { - value: "main" - } - } - } - } - output: { - string: { - value: "c97bdc3bc41acb5c1bebec6fba9994ee2fb992a5" - } - } - } - results: { - input: { - array: { - values: { - string: { - value: "https://github.com/vito/bass-loop" - } - } - values: { - string: { - value: "main" - } - } - } - } - output: { - string: { - value: "4d2df18701653fc9ec705da34fa9e6d70fab465f" - } - } - } - } -} -memos: { - module: { - cmd: { - command: { - name: "git" - } - } - stdin: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine/git" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:23dcd3edfd1d9c7cbb14f7823d07a4934716cfa4d4dbc402d37ee011c440a685" - } - } - } - } - } - } - calls: { - binding: "ls-remote" - results: { - input: { - array: { - values: { - string: { - value: "https://github.com/vito/tabs" - } - } - values: { - string: { - value: "main" - } - } - } - } - output: { - string: { - value: "c97bdc3bc41acb5c1bebec6fba9994ee2fb992a5" - } - } - } - } -} -memos: { - module: { - cmd: { - command: { - name: "git" - } - } - stdin: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine/git" - } - } - } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:760aaf0d59c93f87572ec40dee1efd10a7ea13a78dff1f59a904e908449329ae" - } - } - } - } - } - } - calls: { - binding: "ls-remote" - results: { - input: { - array: { - values: { - string: { - value: "https://github.com/vito/tabs" - } - } - values: { - string: { - value: "main" - } - } - } - } - output: { - string: { - value: "c97bdc3bc41acb5c1bebec6fba9994ee2fb992a5" - } - } - } - } -} -memos: { - module: { - cmd: { - command: { - name: "git" - } - } - stdin: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine/git" - } - } - } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:7b9c96bea8268579e925b17170ae208788e90d508ec334421384913ba61cd610" - } - } - } - } - } - } - calls: { - binding: "ls-remote" - results: { - input: { - array: { - values: { - string: { - value: "https://github.com/vito/tabs" - } - } - values: { - string: { - value: "main" - } - } - } - } - output: { - string: { - value: "c97bdc3bc41acb5c1bebec6fba9994ee2fb992a5" - } - } - } - } -} diff --git a/demos/bass.lock b/demos/bass.lock deleted file mode 100644 index d4915626..00000000 --- a/demos/bass.lock +++ /dev/null @@ -1,248 +0,0 @@ -memos: { - module: { - cmd: { - command: { - name: "run" - } - } - } - calls: { - binding: "resolve" - results: { - input: { - array: { - values: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine/git" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - } - } - } - } - output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine/git" - } - } - } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:760aaf0d59c93f87572ec40dee1efd10a7ea13a78dff1f59a904e908449329ae" - } - } - } - } - } - } - } -} -memos: { - module: { - cmd: { - command: { - name: "git" - } - } - stdin: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine/git" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:5dbc7ef3c51fd64e996c3ca819d625ca21bbc4259be166fd9a46395d5f6c6a1f" - } - } - } - } - } - } - calls: { - binding: "ls-remote" - results: { - input: { - array: { - values: { - string: { - value: "https://github.com/vito/tabs" - } - } - values: { - string: { - value: "main" - } - } - } - } - output: { - string: { - value: "d04ee56d1947e0f7b1178f98915be6cfab1f6198" - } - } - } - } -} -memos: { - module: { - cmd: { - command: { - name: "git" - } - } - stdin: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine/git" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:23dcd3edfd1d9c7cbb14f7823d07a4934716cfa4d4dbc402d37ee011c440a685" - } - } - } - } - } - } - calls: { - binding: "ls-remote" - results: { - input: { - array: { - values: { - string: { - value: "https://github.com/vito/tabs" - } - } - values: { - string: { - value: "main" - } - } - } - } - output: { - string: { - value: "d04ee56d1947e0f7b1178f98915be6cfab1f6198" - } - } - } - } -} diff --git a/docs/go/bass.go b/docs/go/bass.go index c10f3c4d..b4b8a237 100644 --- a/docs/go/bass.go +++ b/docs/go/bass.go @@ -314,7 +314,7 @@ func (plugin *Plugin) bassEval(source booklit.Content) (bass.Value, booklit.Cont evalCtx := ioctx.StderrToContext(ctx, vterm) evalCtx = zapctx.ToContext(evalCtx, initZap(vterm)) file := bass.NewInMemoryFile("docs-eval", source.String()) - res, err := bass.EvalFSFile(ctx, scope, file) + res, err := bass.EvalFSFile(evalCtx, scope, file) if err != nil { return nil, nil, err } @@ -864,7 +864,7 @@ func (plugin *Plugin) renderValue(val bass.Value) (booklit.Content, error) { return plugin.renderList(list) } - return plugin.Bass(booklit.String(fmt.Sprintf("%s", val))) + return plugin.Bass(booklit.String(val.String())) } func (plugin *Plugin) renderScope(scope *bass.Scope) (booklit.Content, error) { @@ -1019,7 +1019,6 @@ func (plugin *Plugin) renderThunk(thunk bass.Thunk, pathOptional ...bass.Value) if thunk.Insecure { thunkScope.Set("insecure", bass.Bool(thunk.Insecure)) } - thunkScope.Set("cmd", thunk.Cmd.ToValue()) if len(thunk.Args) > 0 { thunkScope.Set("args", bass.NewList(thunk.Args...)) } @@ -1051,7 +1050,12 @@ func (plugin *Plugin) renderThunk(thunk bass.Thunk, pathOptional ...bass.Value) return nil, err } - run, err := plugin.renderValue(thunk.Cmd.ToValue()) + var run booklit.Content + if len(thunk.Args) > 0 { + run, err = plugin.renderValue(thunk.Args[0]) + } else { + run = booklit.String("") + } if err != nil { return nil, err } diff --git a/pkg/bass/cache_path.go b/pkg/bass/cache_path.go index 7683d71b..68f43537 100644 --- a/pkg/bass/cache_path.go +++ b/pkg/bass/cache_path.go @@ -100,9 +100,7 @@ var _ Applicative = ThunkPath{} func (app CachePath) Unwrap() Combiner { if app.Path.File != nil { return ThunkOperative{ - Cmd: ThunkCmd{ - Cache: &app, - }, + Cmd: app, } } else { return ExtendOperative{app} diff --git a/pkg/bass/encoding_test.go b/pkg/bass/encoding_test.go index 0fc2b97f..9d146afb 100644 --- a/pkg/bass/encoding_test.go +++ b/pkg/bass/encoding_test.go @@ -68,10 +68,10 @@ var encodable = []bass.Value{ } // minimum viable thunk +var validScratchThunk = bass.Thunk{} + var validBasicThunk = bass.Thunk{ - Cmd: bass.ThunkCmd{ - File: &bass.FilePath{"basic"}, - }, + Args: []bass.Value{bass.FilePath{"basic"}}, } // avoid using bass.Bindings{} so the order is stable @@ -95,28 +95,24 @@ func init() { // a thunk with all "simple" (non-enum) fields filled-in var validThiccThunk = bass.Thunk{ - Cmd: bass.ThunkCmd{ - File: &bass.FilePath{"run"}, - }, Args: []bass.Value{ + bass.FilePath{"run"}, bass.String("arg"), bass.ThunkPath{ - Thunk: bass.Thunk{ - Cmd: bass.ThunkCmd{ - File: &bass.FilePath{"basic"}, - }, - }, + Thunk: bass.Thunk{Args: []bass.Value{ + + bass.FilePath{"basic"}}}, + Path: bass.ParseFileOrDirPath("arg/path/"), }, }, Stdin: []bass.Value{ bass.String("stdin"), bass.ThunkPath{ - Thunk: bass.Thunk{ - Cmd: bass.ThunkCmd{ - File: &bass.FilePath{"basic"}, - }, - }, + Thunk: bass.Thunk{Args: []bass.Value{ + + bass.FilePath{"basic"}}}, + Path: bass.ParseFileOrDirPath("stdin/path/"), }, }, @@ -133,6 +129,9 @@ var validThiccThunk = bass.Thunk{ } var validThunkImages = []bass.ThunkImage{ + { + Thunk: &validScratchThunk, + }, { Thunk: &validBasicThunk, }, @@ -312,34 +311,28 @@ func init() { } } -var validThunkCmds = []bass.ThunkCmd{ - { - Cmd: &bass.CommandPath{"cmd"}, - }, - { - File: &bass.FilePath{"file"}, - }, - { - Thunk: &bass.ThunkPath{ - Thunk: validBasicThunk, - Path: bass.ParseFileOrDirPath("thunk/file"), - }, - }, - { - Host: &bass.HostPath{ - ContextDir: "context-dir", - Path: bass.ParseFileOrDirPath("host/file"), - }, +var validThunkCmds = []bass.Value{ + bass.CommandPath{"cmd"}, + bass.FilePath{"file"}, + bass.ThunkPath{ + Thunk: validBasicThunk, + Path: bass.ParseFileOrDirPath("thunk/file"), }, - { - FS: bass.NewInMemoryFile("fs/dir/cmd-file", "hello"), + bass.HostPath{ + ContextDir: "context-dir", + Path: bass.ParseFileOrDirPath("host/file"), }, + bass.NewInMemoryFile("fs/dir/cmd-file", "hello"), } func init() { + // no command + encodable = append(encodable, validScratchThunk) + + // all commands for _, cmd := range validThunkCmds { thunk := validBasicThunk - thunk.Cmd = cmd + thunk.Args = append([]bass.Value{cmd}, thunk.Args...) encodable = append(encodable, thunk) } } diff --git a/pkg/bass/enums_test.go b/pkg/bass/enums_test.go index f948f084..4b377bc4 100644 --- a/pkg/bass/enums_test.go +++ b/pkg/bass/enums_test.go @@ -36,44 +36,14 @@ func TestEnums(t *testing.T) { bass.CommandPath{"cmd"}, }, }, - { - Enum: &bass.ThunkCmd{}, - Valid: []bass.Value{ - bass.CommandPath{"cmd"}, - bass.FilePath{"file"}, - bass.ThunkPath{ - Thunk: bass.Thunk{ - Cmd: bass.ThunkCmd{ - Cmd: &bass.CommandPath{"cmd"}, - }, - }, - Path: bass.FileOrDirPath{ - File: &bass.FilePath{"file"}, - }, - }, - }, - Invalid: []bass.Value{ - bass.DirPath{"dir"}, - bass.ThunkPath{ - Thunk: bass.Thunk{ - Cmd: bass.ThunkCmd{ - Cmd: &bass.CommandPath{"cmd"}, - }, - }, - Path: bass.FileOrDirPath{ - Dir: &bass.DirPath{"dir"}, - }, - }, - }, - }, { Enum: &bass.ThunkDir{}, Valid: []bass.Value{ bass.DirPath{"dir"}, bass.ThunkPath{ Thunk: bass.Thunk{ - Cmd: bass.ThunkCmd{ - Cmd: &bass.CommandPath{"cmd"}, + Args: []bass.Value{ + bass.CommandPath{"cmd"}, }, }, Path: bass.FileOrDirPath{ @@ -86,8 +56,8 @@ func TestEnums(t *testing.T) { bass.FilePath{"file"}, bass.ThunkPath{ Thunk: bass.Thunk{ - Cmd: bass.ThunkCmd{ - Cmd: &bass.CommandPath{"cmd"}, + Args: []bass.Value{ + bass.CommandPath{"cmd"}, }, }, Path: bass.FileOrDirPath{ @@ -107,8 +77,8 @@ func TestEnums(t *testing.T) { "repository": bass.String("repo"), }.Scope(), bass.Thunk{ - Cmd: bass.ThunkCmd{ - Cmd: &bass.CommandPath{"cmd"}, + Args: []bass.Value{ + bass.CommandPath{"cmd"}, }, }, }, diff --git a/pkg/bass/fspath.go b/pkg/bass/fspath.go index 98ec6e9d..6004cbe2 100644 --- a/pkg/bass/fspath.go +++ b/pkg/bass/fspath.go @@ -90,9 +90,7 @@ var _ Applicative = ThunkPath{} func (app *FSPath) Unwrap() Combiner { if app.Path.File != nil { return ThunkOperative{ - Cmd: ThunkCmd{ - FS: app, - }, + Cmd: app, } } else { return ExtendOperative{app} diff --git a/pkg/bass/ground.go b/pkg/bass/ground.go index 2fab4a3f..cc42b116 100644 --- a/pkg/bass/ground.go +++ b/pkg/bass/ground.go @@ -646,6 +646,8 @@ func init() { ) // thunk constructors + Ground.Set("scratch", Thunk{}, `an empty thunk`) + Ground.Set("with-image", Func("with-image", "[thunk image]", (Thunk).WithImage), `returns thunk with the base image set to image`, @@ -667,10 +669,13 @@ func init() { `returns thunk with args set to args`, `=> (with-args (.go) ["test" "./..."])`) - Ground.Set("with-cmd", - Func("with-cmd", "[thunk cmd]", (Thunk).WithCmd), - `returns thunk with cmd set to cmd`, - `=> (let [inner (with-args (.go) ["build"])] (with-args (with-cmd inner ./wrapped) (cons (thunk-cmd inner) (thunk-args inner))))`) + Ground.Set("with-entrypoint", + Func("with-entrypoint", "[thunk entrypoint]", (Thunk).WithEntrypoint), + `returns thunk with entrypoint set to entrypoint`) + + Ground.Set("with-default-args", + Func("with-default-args", "[thunk args]", (Thunk).WithDefaultArgs), + `returns thunk with default args set to args`) Ground.Set("with-stdin", Func("with-stdin", "[thunk vals]", (Thunk).WithStdin), @@ -710,14 +715,6 @@ func init() { `returns thunk with a mount from source to the target path`, `=> (with-mount ($ find ./inputs/) *dir*/inputs/ ./inputs/)`) - Ground.Set("thunk-cmd", - Func("thunk-cmd", "[thunk]", func(thunk Thunk) Value { - return thunk.Cmd.ToValue() - }), - `returns the thunk's command`, - `=> (thunk-cmd (.foo))`, - `=> (thunk-cmd (./foo))`) - Ground.Set("thunk-args", Func("thunk-args", "[thunk]", func(thunk Thunk) Value { return NewList(thunk.Args...) diff --git a/pkg/bass/ground_test.go b/pkg/bass/ground_test.go index c42a1e8a..784606be 100644 --- a/pkg/bass/ground_test.go +++ b/pkg/bass/ground_test.go @@ -409,8 +409,8 @@ func TestGroundPrimitivePredicates(t *testing.T) { Name: "thunk?", Trues: []bass.Value{ bass.Thunk{ - Cmd: bass.ThunkCmd{ - Cmd: &bass.CommandPath{"foo"}, + Args: []bass.Value{ + bass.FilePath{"foo"}, }, }, }, @@ -1796,8 +1796,8 @@ func TestGroundPaths(t *testing.T) { Bass: `(subpath (.foo) ./sub/)`, Result: bass.ThunkPath{ Thunk: bass.Thunk{ - Cmd: bass.ThunkCmd{ - Cmd: &bass.CommandPath{"foo"}, + Args: []bass.Value{ + bass.CommandPath{"foo"}, }, }, Path: bass.FileOrDirPath{ @@ -1810,8 +1810,8 @@ func TestGroundPaths(t *testing.T) { Bass: `(let [wl (.foo) wl-dir (subpath wl ./dir/)] (subpath wl-dir ./file))`, Result: bass.ThunkPath{ Thunk: bass.Thunk{ - Cmd: bass.ThunkCmd{ - Cmd: &bass.CommandPath{"foo"}, + Args: []bass.Value{ + bass.CommandPath{"foo"}, }, }, Path: bass.FileOrDirPath{ diff --git a/pkg/bass/host_path.go b/pkg/bass/host_path.go index 3ecd7cc8..a015187f 100644 --- a/pkg/bass/host_path.go +++ b/pkg/bass/host_path.go @@ -158,9 +158,7 @@ var _ Applicative = ThunkPath{} func (app HostPath) Unwrap() Combiner { if app.Path.File != nil { return ThunkOperative{ - Cmd: ThunkCmd{ - Host: &app, - }, + Cmd: app, } } else { return ExtendOperative{app} diff --git a/pkg/bass/memo_test.go b/pkg/bass/memo_test.go index 102ac213..37ce84e6 100644 --- a/pkg/bass/memo_test.go +++ b/pkg/bass/memo_test.go @@ -91,7 +91,7 @@ func TestOpenMemosThunkPath(t *testing.T) { Platform: fakePlatform, }, }, - Cmd: bass.ThunkCmd{Cmd: &bass.CommandPath{"foo"}}, + Args: []bass.Value{bass.CommandPath{"foo"}}, } t.Run("file exists", func(t *testing.T) { @@ -156,7 +156,7 @@ func TestLockfileMemoConcurrentWrites(t *testing.T) { memos := bass.NewLockfileMemo(filepath.Join(dir, "test.lock")) - thunk := bass.Thunk{Cmd: bass.ThunkCmd{Cmd: &bass.CommandPath{"foo"}}} + thunk := bass.Thunk{Args: []bass.Value{bass.CommandPath{"foo"}}} eg := new(errgroup.Group) for i := 0; i < 100; i++ { @@ -182,8 +182,8 @@ func TestLockfileMemoConcurrentWrites(t *testing.T) { func testRW(t *testing.T, memos bass.Memos, bassLock string) { is := is.New(t) - thunk1 := bass.Thunk{Cmd: bass.ThunkCmd{Cmd: &bass.CommandPath{"foo"}}} - thunk2 := bass.Thunk{Cmd: bass.ThunkCmd{Cmd: &bass.CommandPath{"bar"}}} + thunk1 := bass.Thunk{Args: []bass.Value{bass.CommandPath{"foo"}}} + thunk2 := bass.Thunk{Args: []bass.Value{bass.CommandPath{"bar"}}} // no initial value _, found, err := memos.Retrieve(thunk1, "bnd", bass.String("a")) diff --git a/pkg/bass/path.go b/pkg/bass/path.go index 7a72f387..fe3e5a1e 100644 --- a/pkg/bass/path.go +++ b/pkg/bass/path.go @@ -234,9 +234,7 @@ var _ Applicative = FilePath{} func (app FilePath) Unwrap() Combiner { return ThunkOperative{ - Cmd: ThunkCmd{ - File: &app, - }, + Cmd: app, } } @@ -357,9 +355,7 @@ var _ Applicative = CommandPath{} func (app CommandPath) Unwrap() Combiner { return ThunkOperative{ - Cmd: ThunkCmd{ - Cmd: &app, - }, + Cmd: app, } } @@ -462,13 +458,13 @@ func (ExtendPath) EachBinding(func(Symbol, Range) error) error { // ThunkOperative is an operative which constructs a Thunk. type ThunkOperative struct { - Cmd ThunkCmd + Cmd Value } var _ Value = ThunkOperative{} func (value ThunkOperative) String() string { - return fmt.Sprintf("(unwrap %s)", value.Cmd.ToValue()) + return fmt.Sprintf("(unwrap %s)", value.Cmd) } func (value ThunkOperative) Equal(other Value) bool { @@ -511,7 +507,7 @@ func (op ThunkOperative) Call(_ context.Context, args Value, _ *Scope, cont Cont } return cont.Call(Thunk{ - Cmd: op.Cmd, + Args: []Value{op.Cmd}, Stdin: stdin, }, nil) } diff --git a/pkg/bass/proto.go b/pkg/bass/proto.go index 9cfad56a..913046cf 100644 --- a/pkg/bass/proto.go +++ b/pkg/bass/proto.go @@ -75,6 +75,11 @@ func FromProto(val *proto.Value) (Value, error) { ContextDir: x.HostPath.Context, Path: fod(x.HostPath.Path), }, nil + case *proto.Value_CachePath: + return CachePath{ + ID: x.CachePath.Id, + Path: fod(x.CachePath.Path), + }, nil case *proto.Value_LogicalPath: fsp := &FSPath{} if err := fsp.UnmarshalProto(x.LogicalPath); err != nil { @@ -329,13 +334,6 @@ func (value Thunk) MarshalProto() (proto.Message, error) { thunk.Image = ti.(*proto.ThunkImage) } - ci, err := value.Cmd.MarshalProto() - if err != nil { - return nil, fmt.Errorf("command: %w", err) - } - - thunk.Cmd = ci.(*proto.ThunkCmd) - for i, v := range value.Args { pv, err := MarshalProto(v) if err != nil { diff --git a/pkg/bass/session.go b/pkg/bass/session.go index 40115c0a..c31cdca4 100644 --- a/pkg/bass/session.go +++ b/pkg/bass/session.go @@ -2,6 +2,7 @@ package bass import ( "context" + "errors" "fmt" "io" "path/filepath" @@ -77,23 +78,36 @@ func (session *Session) run(ctx context.Context, thunk Thunk, state RunState, ru var module *Scope - if thunk.Cmd.Cmd != nil { - cp := thunk.Cmd.Cmd + if len(thunk.Args) == 0 { + return nil, errors.New("Bass thunk has no command") + } + + cmd := thunk.Args[0] + + var ok bool + + var cmdp CommandPath + if cmd.Decode(&cmdp) == nil { + ok = true + state.Dir = NewFSDir(std.FS) module = NewRunScope(NewEmptyScope(session.Root, Internal), state) source := NewFSPath( std.FS, - ParseFileOrDirPath(cp.Command+Ext), + ParseFileOrDirPath(cmdp.Command+Ext), ) _, err := EvalFSFile(ctx, module, source) if err != nil { return nil, err } - } else if thunk.Cmd.Host != nil { - hostp := *thunk.Cmd.Host + } + + var hostp HostPath + if cmd.Decode(&hostp) == nil { + ok = true fp := filepath.Join(hostp.FromSlash()) abs, err := filepath.Abs(filepath.Dir(fp)) @@ -109,10 +123,15 @@ func (session *Session) run(ctx context.Context, thunk Thunk, state RunState, ru if err != nil { return nil, err } - } else if thunk.Cmd.Thunk != nil { + } + + var thunkp ThunkPath + if cmd.Decode(&thunkp) == nil { + ok = true + source := ThunkPath{ - Thunk: thunk.Cmd.Thunk.Thunk, - Path: FilePath{Path: thunk.Cmd.Thunk.Path.File.Path}.FileOrDir(), + Thunk: thunkp.Thunk, + Path: FilePath{Path: thunkp.Path.File.Path}.FileOrDir(), } modFile, err := source.CachePath(ctx, CacheHome) @@ -120,7 +139,7 @@ func (session *Session) run(ctx context.Context, thunk Thunk, state RunState, ru return nil, err } - state.Dir = thunk.Cmd.Thunk.Dir() + state.Dir = thunkp.Dir() module = NewRunScope(session.Root, state) @@ -128,8 +147,11 @@ func (session *Session) run(ctx context.Context, thunk Thunk, state RunState, ru if err != nil { return nil, err } - } else if thunk.Cmd.FS != nil { - fsp := thunk.Cmd.FS + } + + var fsp *FSPath + if cmd.Decode(&fsp) == nil { + ok = true dir := fsp.Path.File.Dir() state.Dir = NewFSPath(fsp.FS, FileOrDirPath{Dir: &dir}) @@ -140,16 +162,20 @@ func (session *Session) run(ctx context.Context, thunk Thunk, state RunState, ru if err != nil { return nil, err } - } else if thunk.Cmd.File != nil { + } + + var filep FilePath + if cmd.Decode(&filep) == nil { // TODO: better error - return nil, fmt.Errorf("bad path: did you mean *dir*/%s? (. is only resolveable in a container)", thunk.Cmd.File) - } else { - val := thunk.Cmd.ToValue() - return nil, fmt.Errorf("impossible: unknown thunk path type %T: %s", val, val) + return nil, fmt.Errorf("bad path: did you mean *dir*/%s? (. is only resolveable in a container)", filep.Path) + } + + if !ok { + return nil, fmt.Errorf("impossible: unknown thunk path type %T: %s", cmd, cmd) } if runMain { - err := RunMain(ctx, module, thunk.Args...) + err := RunMain(ctx, module, thunk.Args[1:]...) if err != nil { return nil, err } diff --git a/pkg/bass/session_test.go b/pkg/bass/session_test.go index 230a65b0..439bf3bc 100644 --- a/pkg/bass/session_test.go +++ b/pkg/bass/session_test.go @@ -52,8 +52,8 @@ func (test sessionTest) Run(t *testing.T) { ctx = ioctx.StderrToContext(ctx, os.Stderr) err := bass.NewBass().Run(ctx, bass.Thunk{ - Cmd: bass.ThunkCmd{ - FS: bass.NewFSPath(testdata.FS, bass.ParseFileOrDirPath(test.File)), + Args: []bass.Value{ + bass.NewFSPath(testdata.FS, bass.ParseFileOrDirPath(test.File)), }, }, bass.RunState{}) is.NoErr(err) @@ -92,8 +92,8 @@ func TestSessionClosesSources(t *testing.T) { is.NoErr(session.Run( context.Background(), bass.Thunk{ - Cmd: bass.ThunkCmd{ - FS: bass.NewFSPath(testdata.FS, bass.ParseFileOrDirPath("read.bass")), + Args: []bass.Value{ + bass.NewFSPath(testdata.FS, bass.ParseFileOrDirPath("read.bass")), }, }, bass.RunState{}, diff --git a/pkg/bass/thunk.go b/pkg/bass/thunk.go index 9e90a32f..78e551fc 100644 --- a/pkg/bass/thunk.go +++ b/pkg/bass/thunk.go @@ -13,6 +13,7 @@ import ( "sync" "github.com/vito/bass/pkg/proto" + "github.com/vito/bass/std" "github.com/vito/invaders" "github.com/zeebo/xxh3" "google.golang.org/protobuf/encoding/protojson" @@ -27,10 +28,7 @@ type Thunk struct { // privileges. Its meaning is determined by the runtime. Insecure bool `json:"insecure,omitempty"` - // Cmd identifies the file or command to run. - Cmd ThunkCmd `json:"cmd"` - - // Args is a list of string or path arguments to pass to the command. + // Args is a list of string or path arguments. Args []Value `json:"args,omitempty"` // Stdin is a list of arbitrary values, which may contain paths, to pass to @@ -78,6 +76,16 @@ type Thunk struct { // TLS configures paths to place generated certificates. TLS *ThunkTLS `json:"tls,omitempty"` + + // Entrypoint configures a static command and arguments that will be + // prepended to child commands. + // + // A nil value inherits from the parent. An empty slice removes it. + Entrypoint []string `json:"entrypoint,omitempty"` + + // DefaultArgs configures a command and arguments to use if a child execution + // does not specify a command. + DefaultArgs []string `json:"default_args,omitempty"` } type ThunkPort struct { @@ -105,12 +113,6 @@ func (thunk *Thunk) UnmarshalProto(msg proto.Message) error { thunk.Insecure = p.Insecure - if p.Cmd != nil { - if err := thunk.Cmd.UnmarshalProto(p.Cmd); err != nil { - return err - } - } - for i, arg := range p.Args { val, err := FromProto(arg) if err != nil { @@ -197,13 +199,8 @@ func (thunk *Thunk) UnmarshalProto(msg proto.Message) error { } func MustThunk(cmd Path, stdin ...Value) Thunk { - var thunkCmd ThunkCmd - if err := cmd.Decode(&thunkCmd); err != nil { - panic(fmt.Sprintf("MustParse: %s", err)) - } - return Thunk{ - Cmd: thunkCmd, + Args: []Value{cmd}, Stdin: stdin, } } @@ -225,13 +222,43 @@ func (thunk Thunk) Run(ctx context.Context) error { func (thunk Thunk) RunState(stdout io.Writer) RunState { return RunState{ - Dir: thunk.Cmd.RunDir(), + Dir: thunk.RunDir(), Env: thunk.Env, Stdin: NewSource(NewInMemorySource(thunk.Stdin...)), Stdout: NewSink(NewJSONSink(thunk.String(), stdout)), } } +func (thunk Thunk) RunDir() Path { + if len(thunk.Args) == 0 { + panic(fmt.Sprintf("Thunk.RunDir: no arguments: %+v", thunk)) + } + + cmd := thunk.Args[0] + + var filep FilePath + var thunkp ThunkPath + var cmdp CommandPath + var hostp HostPath + var fsp *FSPath + var cachep CachePath + if cmd.Decode(&filep) == nil { + return filep.Dir() + } else if cmd.Decode(&thunkp) == nil { + return thunkp.Dir() + } else if cmd.Decode(&cmdp) == nil { + return NewFSDir(std.FS) + } else if cmd.Decode(&hostp) == nil { + return hostp.Dir() + } else if cmd.Decode(&fsp) == nil { + return fsp.Dir() + } else if cmd.Decode(&cachep) == nil { + return cachep.Dir() + } else { + panic(fmt.Sprintf("ThunkCmd.RunDir: no value present: %+v", cmd)) + } +} + func (thunk Thunk) Read(ctx context.Context, w io.Writer) error { platform := thunk.Platform() @@ -370,14 +397,6 @@ func (thunk Thunk) Open(ctx context.Context) (io.ReadCloser, error) { func (thunk Thunk) Cmdline() string { var cmdline []string - cmdPath := thunk.Cmd.ToValue() - var cmd CommandPath - if err := cmdPath.Decode(&cmd); err == nil { - cmdline = append(cmdline, cmd.Name()) - } else { - cmdline = append(cmdline, cmdPath.String()) - } - for _, arg := range thunk.Args { var str string if err := arg.Decode(&str); err == nil && !strings.Contains(str, " ") { @@ -405,9 +424,15 @@ func (thunk Thunk) WithImage(image ThunkImage) Thunk { return thunk } -// WithArgs sets the thunk's command. -func (thunk Thunk) WithCmd(cmd ThunkCmd) Thunk { - thunk.Cmd = cmd +// WithEntrypoint sets the thunk's entrypoint. +func (thunk Thunk) WithEntrypoint(entrypoint []string) Thunk { + thunk.Entrypoint = entrypoint + return thunk +} + +// WithDefaultArgs sets the thunk's default arguments. +func (thunk Thunk) WithDefaultArgs(args []string) Thunk { + thunk.DefaultArgs = args return thunk } @@ -493,7 +518,7 @@ func (thunk Thunk) WithTLS(cert, key FilePath) Thunk { var _ Value = Thunk{} func (thunk Thunk) String() string { - return fmt.Sprintf("", thunk.Name(), NewList(thunk.Cmd.ToValue())) + return fmt.Sprintf("", thunk.Name(), NewList(thunk.Args...)) } func (thunk Thunk) Equal(other Value) bool { diff --git a/pkg/bass/thunk_path.go b/pkg/bass/thunk_path.go index d68aecc6..f6a8bfdd 100644 --- a/pkg/bass/thunk_path.go +++ b/pkg/bass/thunk_path.go @@ -107,9 +107,7 @@ var _ Applicative = ThunkPath{} func (app ThunkPath) Unwrap() Combiner { if app.Path.File != nil { return ThunkOperative{ - Cmd: ThunkCmd{ - Thunk: &app, - }, + Cmd: app, } } else { return ExtendOperative{app} diff --git a/pkg/bass/thunk_path_test.go b/pkg/bass/thunk_path_test.go index 2de45022..c557a08e 100644 --- a/pkg/bass/thunk_path_test.go +++ b/pkg/bass/thunk_path_test.go @@ -14,8 +14,8 @@ func TestThunkPathJSON(t *testing.T) { wlp := bass.ThunkPath{ Thunk: bass.Thunk{ - Cmd: bass.ThunkCmd{ - File: &bass.FilePath{"run"}, + Args: []bass.Value{ + bass.FilePath{"run"}, }, }, Path: bass.FileOrDirPath{ @@ -38,8 +38,8 @@ func TestThunkPathEqual(t *testing.T) { wlp := bass.ThunkPath{ Thunk: bass.Thunk{ - Cmd: bass.ThunkCmd{ - File: &bass.FilePath{"run"}, + Args: []bass.Value{ + bass.FilePath{"run"}, }, }, Path: bass.FileOrDirPath{ @@ -61,8 +61,8 @@ func TestThunkPathDecode(t *testing.T) { wlp := bass.ThunkPath{ Thunk: bass.Thunk{ - Cmd: bass.ThunkCmd{ - File: &bass.FilePath{"run"}, + Args: []bass.Value{ + bass.FilePath{"run"}, }, }, Path: bass.FileOrDirPath{ @@ -95,8 +95,8 @@ func TestThunkPathName(t *testing.T) { is := is.New(t) wl := bass.Thunk{ - Cmd: bass.ThunkCmd{ - File: &bass.FilePath{"run"}, + Args: []bass.Value{ + bass.FilePath{"run"}, }, } @@ -117,8 +117,8 @@ func TestThunkPathExtend(t *testing.T) { var parent, child bass.Path wl := bass.Thunk{ - Cmd: bass.ThunkCmd{ - File: &bass.FilePath{"run"}, + Args: []bass.Value{ + bass.FilePath{"run"}, }, } diff --git a/pkg/bass/thunk_test.go b/pkg/bass/thunk_test.go index dedf8ff7..a901be1e 100644 --- a/pkg/bass/thunk_test.go +++ b/pkg/bass/thunk_test.go @@ -18,11 +18,9 @@ func TestThunkHash(t *testing.T) { } thunk := bass.Thunk{ - Cmd: bass.ThunkCmd{ - File: &bass.FilePath{"run"}, - }, Env: manyKeys, Args: []bass.Value{ + bass.FilePath{"run"}, // ensure HTML characters are not escaped bass.String("foo >> bar"), }, @@ -33,5 +31,5 @@ func TestThunkHash(t *testing.T) { // this is a bit silly, but it's deterministic, and we need to make sure it's // always the same value - is.Equal(hash, "PM31VIOOJVOPK") + is.Equal(hash, "LCV6HSUTK70GE") } diff --git a/pkg/bass/thunk_types.go b/pkg/bass/thunk_types.go index f75eee40..24c84b71 100644 --- a/pkg/bass/thunk_types.go +++ b/pkg/bass/thunk_types.go @@ -8,7 +8,6 @@ import ( "github.com/hashicorp/go-multierror" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/vito/bass/pkg/proto" - "github.com/vito/bass/std" ) // ThunkMount configures a mount for the thunk. @@ -551,230 +550,6 @@ func (image *ThunkImage) FromValue(val Value) error { return fmt.Errorf("image enum: %w", errs) } -type ThunkCmd struct { - Cmd *CommandPath - File *FilePath - Thunk *ThunkPath - Host *HostPath - FS *FSPath - Cache *CachePath -} - -func (cmd *ThunkCmd) UnmarshalProto(msg proto.Message) error { - p, ok := msg.(*proto.ThunkCmd) - if !ok { - return fmt.Errorf("unmarshal proto: %w", DecodeError{msg, cmd}) - } - - var err error - switch x := p.GetCmd().(type) { - case *proto.ThunkCmd_Command: - cmd.Cmd = &CommandPath{} - err = cmd.Cmd.UnmarshalProto(x.Command) - case *proto.ThunkCmd_File: - cmd.File = &FilePath{} - err = cmd.File.UnmarshalProto(x.File) - case *proto.ThunkCmd_Thunk: - cmd.Thunk = &ThunkPath{} - err = cmd.Thunk.UnmarshalProto(x.Thunk) - case *proto.ThunkCmd_Host: - cmd.Host = &HostPath{} - err = cmd.Host.UnmarshalProto(x.Host) - case *proto.ThunkCmd_Logical: - cmd.FS = &FSPath{} - err = cmd.FS.UnmarshalProto(x.Logical) - case *proto.ThunkCmd_Cache: - cmd.Cache = &CachePath{} - err = cmd.Cache.UnmarshalProto(x.Cache) - default: - return fmt.Errorf("unhandled cmd type: %T", x) - } - - return err -} - -func (cmd ThunkCmd) MarshalProto() (proto.Message, error) { - pv := &proto.ThunkCmd{} - - if cmd.Cmd != nil { - cv, err := cmd.Cmd.MarshalProto() - if err != nil { - return nil, err - } - - pv.Cmd = &proto.ThunkCmd_Command{ - Command: cv.(*proto.CommandPath), - } - } else if cmd.File != nil { - cv, err := cmd.File.MarshalProto() - if err != nil { - return nil, err - } - - pv.Cmd = &proto.ThunkCmd_File{ - File: cv.(*proto.FilePath), - } - } else if cmd.Thunk != nil { - cv, err := cmd.Thunk.MarshalProto() - if err != nil { - return nil, err - } - - pv.Cmd = &proto.ThunkCmd_Thunk{ - Thunk: cv.(*proto.ThunkPath), - } - } else if cmd.Host != nil { - cv, err := cmd.Host.MarshalProto() - if err != nil { - return nil, err - } - - pv.Cmd = &proto.ThunkCmd_Host{ - Host: cv.(*proto.HostPath), - } - } else if cmd.FS != nil { - cv, err := cmd.FS.MarshalProto() - if err != nil { - return nil, err - } - - pv.Cmd = &proto.ThunkCmd_Logical{ - Logical: cv.(*proto.LogicalPath), - } - } else if cmd.Cache != nil { - cv, err := cmd.Cache.MarshalProto() - if err != nil { - return nil, err - } - - pv.Cmd = &proto.ThunkCmd_Cache{ - Cache: cv.(*proto.CachePath), - } - } else { - return nil, fmt.Errorf("unexpected command type: %T", cmd.ToValue()) - } - - return pv, nil -} - -var _ Decodable = &ThunkCmd{} -var _ Encodable = ThunkCmd{} - -func (cmd ThunkCmd) ToValue() Value { - val, err := cmd.Inner() - if err != nil { - panic(err) - } - - return val -} - -func (cmd ThunkCmd) Inner() (Value, error) { - if cmd.File != nil { - return *cmd.File, nil - } else if cmd.Thunk != nil { - return *cmd.Thunk, nil - } else if cmd.Cmd != nil { - return *cmd.Cmd, nil - } else if cmd.Host != nil { - return *cmd.Host, nil - } else if cmd.FS != nil { - return cmd.FS, nil - } else if cmd.Cache != nil { - return cmd.Cache, nil - } else { - return nil, fmt.Errorf("no value present for thunk command: %+v", cmd) - } -} - -func (cmd ThunkCmd) RunDir() Path { - if cmd.File != nil { - return cmd.File.Dir() - } else if cmd.Thunk != nil { - return cmd.Thunk.Dir() - } else if cmd.Cmd != nil { - return NewFSDir(std.FS) - } else if cmd.Host != nil { - return cmd.Host.Dir() - } else if cmd.FS != nil { - return cmd.FS.Dir() - } else if cmd.Cache != nil { - return cmd.Cache.Dir() - } else { - panic(fmt.Sprintf("ThunkCmd.RunDir: no value present: %+v", cmd)) - } -} - -func (path *ThunkCmd) UnmarshalJSON(payload []byte) error { - return UnmarshalJSON(payload, path) -} - -func (tc ThunkCmd) MarshalJSON() ([]byte, error) { - val, err := tc.Inner() - if err != nil { - return nil, err - - } - return MarshalJSON(val) -} - -func (tc *ThunkCmd) FromValue(val Value) error { - var errs error - var file FilePath - if err := val.Decode(&file); err == nil { - tc.File = &file - return nil - } else { - errs = multierror.Append(errs, fmt.Errorf("%T: %w", file, err)) - } - - var cmd CommandPath - if err := val.Decode(&cmd); err == nil { - tc.Cmd = &cmd - return nil - } else { - errs = multierror.Append(errs, fmt.Errorf("%T: %w", cmd, err)) - } - - var wlp ThunkPath - if err := val.Decode(&wlp); err == nil { - if wlp.Path.File != nil { - tc.Thunk = &wlp - return nil - } else { - errs = multierror.Append(errs, fmt.Errorf("%T does not point to a File", wlp)) - } - } else { - errs = multierror.Append(errs, fmt.Errorf("%T: %w", wlp, err)) - } - - var host HostPath - if err := val.Decode(&host); err == nil { - tc.Host = &host - return nil - } else { - errs = multierror.Append(errs, fmt.Errorf("%T: %w", file, err)) - } - - var fsp *FSPath - if err := val.Decode(&fsp); err == nil { - tc.FS = fsp - return nil - } else { - errs = multierror.Append(errs, fmt.Errorf("%T: %w", file, err)) - } - - var cache CachePath - if err := val.Decode(&cache); err == nil { - tc.Cache = &cache - return nil - } else { - errs = multierror.Append(errs, fmt.Errorf("%T: %w", file, err)) - } - - return errs -} - type ThunkDir struct { Dir *DirPath ThunkDir *ThunkPath diff --git a/pkg/bass/value_test.go b/pkg/bass/value_test.go index 7d3784de..72f04f2e 100644 --- a/pkg/bass/value_test.go +++ b/pkg/bass/value_test.go @@ -43,8 +43,8 @@ var allConstValues = []bass.Value{ }, bass.ThunkPath{ Thunk: bass.Thunk{ - Cmd: bass.ThunkCmd{ - File: &bass.FilePath{"file"}, + Args: []bass.Value{ + bass.FilePath{"file"}, }, }, Path: bass.FileOrDirPath{ @@ -462,15 +462,15 @@ func TestString(t *testing.T) { { bass.ThunkPath{ Thunk: bass.Thunk{ - Cmd: bass.ThunkCmd{ - File: &bass.FilePath{"file"}, + Args: []bass.Value{ + bass.FilePath{"file"}, }, }, Path: bass.FileOrDirPath{ Dir: &bass.DirPath{"dir"}, }, }, - "/dir/", + "/dir/", }, } { t.Run(fmt.Sprintf("%T", test.src), func(t *testing.T) { diff --git a/pkg/cli/run.go b/pkg/cli/run.go index 67cfe30d..932c541e 100644 --- a/pkg/cli/run.go +++ b/pkg/cli/run.go @@ -18,10 +18,8 @@ func Run(ctx context.Context, env *bass.Scope, inputs []string, filePath string, ) thunk := bass.Thunk{ - Cmd: bass.ThunkCmd{ - Host: &cmd, - }, - Env: env, + Args: []bass.Value{cmd}, + Env: env, } for _, arg := range argv { diff --git a/pkg/proto/bass.pb.go b/pkg/proto/bass.pb.go index 7281d965..1372d94d 100644 --- a/pkg/proto/bass.pb.go +++ b/pkg/proto/bass.pb.go @@ -42,6 +42,7 @@ type Value struct { // *Value_ThunkPath // *Value_LogicalPath // *Value_ThunkAddr + // *Value_CachePath Value isValue_Value `protobuf_oneof:"value"` } @@ -189,6 +190,13 @@ func (x *Value) GetThunkAddr() *ThunkAddr { return nil } +func (x *Value) GetCachePath() *CachePath { + if x, ok := x.GetValue().(*Value_CachePath); ok { + return x.CachePath + } + return nil +} + type isValue_Value interface { isValue_Value() } @@ -253,6 +261,10 @@ type Value_ThunkAddr struct { ThunkAddr *ThunkAddr `protobuf:"bytes,15,opt,name=thunk_addr,json=thunkAddr,proto3,oneof"` } +type Value_CachePath struct { + CachePath *CachePath `protobuf:"bytes,16,opt,name=cache_path,json=cachePath,proto3,oneof"` +} + func (*Value_Null) isValue_Value() {} func (*Value_Bool) isValue_Value() {} @@ -283,6 +295,8 @@ func (*Value_LogicalPath) isValue_Value() {} func (*Value_ThunkAddr) isValue_Value() {} +func (*Value_CachePath) isValue_Value() {} + type Thunk struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -290,7 +304,6 @@ type Thunk struct { Image *ThunkImage `protobuf:"bytes,1,opt,name=image,proto3" json:"image,omitempty"` Insecure bool `protobuf:"varint,2,opt,name=insecure,proto3" json:"insecure,omitempty"` - Cmd *ThunkCmd `protobuf:"bytes,3,opt,name=cmd,proto3" json:"cmd,omitempty"` Args []*Value `protobuf:"bytes,4,rep,name=args,proto3" json:"args,omitempty"` Stdin []*Value `protobuf:"bytes,5,rep,name=stdin,proto3" json:"stdin,omitempty"` Env []*Binding `protobuf:"bytes,6,rep,name=env,proto3" json:"env,omitempty"` @@ -347,13 +360,6 @@ func (x *Thunk) GetInsecure() bool { return false } -func (x *Thunk) GetCmd() *ThunkCmd { - if x != nil { - return x.Cmd - } - return nil -} - func (x *Thunk) GetArgs() []*Value { if x != nil { return x.Args @@ -1160,143 +1166,6 @@ func (x *Platform) GetArch() string { return "" } -type ThunkCmd struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Cmd: - // - // *ThunkCmd_Command - // *ThunkCmd_File - // *ThunkCmd_Thunk - // *ThunkCmd_Host - // *ThunkCmd_Logical - // *ThunkCmd_Cache - Cmd isThunkCmd_Cmd `protobuf_oneof:"cmd"` -} - -func (x *ThunkCmd) Reset() { - *x = ThunkCmd{} - if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ThunkCmd) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ThunkCmd) ProtoMessage() {} - -func (x *ThunkCmd) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ThunkCmd.ProtoReflect.Descriptor instead. -func (*ThunkCmd) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{12} -} - -func (m *ThunkCmd) GetCmd() isThunkCmd_Cmd { - if m != nil { - return m.Cmd - } - return nil -} - -func (x *ThunkCmd) GetCommand() *CommandPath { - if x, ok := x.GetCmd().(*ThunkCmd_Command); ok { - return x.Command - } - return nil -} - -func (x *ThunkCmd) GetFile() *FilePath { - if x, ok := x.GetCmd().(*ThunkCmd_File); ok { - return x.File - } - return nil -} - -func (x *ThunkCmd) GetThunk() *ThunkPath { - if x, ok := x.GetCmd().(*ThunkCmd_Thunk); ok { - return x.Thunk - } - return nil -} - -func (x *ThunkCmd) GetHost() *HostPath { - if x, ok := x.GetCmd().(*ThunkCmd_Host); ok { - return x.Host - } - return nil -} - -func (x *ThunkCmd) GetLogical() *LogicalPath { - if x, ok := x.GetCmd().(*ThunkCmd_Logical); ok { - return x.Logical - } - return nil -} - -func (x *ThunkCmd) GetCache() *CachePath { - if x, ok := x.GetCmd().(*ThunkCmd_Cache); ok { - return x.Cache - } - return nil -} - -type isThunkCmd_Cmd interface { - isThunkCmd_Cmd() -} - -type ThunkCmd_Command struct { - Command *CommandPath `protobuf:"bytes,1,opt,name=command,proto3,oneof"` -} - -type ThunkCmd_File struct { - File *FilePath `protobuf:"bytes,2,opt,name=file,proto3,oneof"` -} - -type ThunkCmd_Thunk struct { - Thunk *ThunkPath `protobuf:"bytes,3,opt,name=thunk,proto3,oneof"` -} - -type ThunkCmd_Host struct { - Host *HostPath `protobuf:"bytes,4,opt,name=host,proto3,oneof"` -} - -type ThunkCmd_Logical struct { - Logical *LogicalPath `protobuf:"bytes,5,opt,name=logical,proto3,oneof"` -} - -type ThunkCmd_Cache struct { - Cache *CachePath `protobuf:"bytes,6,opt,name=cache,proto3,oneof"` -} - -func (*ThunkCmd_Command) isThunkCmd_Cmd() {} - -func (*ThunkCmd_File) isThunkCmd_Cmd() {} - -func (*ThunkCmd_Thunk) isThunkCmd_Cmd() {} - -func (*ThunkCmd_Host) isThunkCmd_Cmd() {} - -func (*ThunkCmd_Logical) isThunkCmd_Cmd() {} - -func (*ThunkCmd_Cache) isThunkCmd_Cmd() {} - type ThunkDir struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1313,7 +1182,7 @@ type ThunkDir struct { func (x *ThunkDir) Reset() { *x = ThunkDir{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[13] + mi := &file_bass_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1326,7 +1195,7 @@ func (x *ThunkDir) String() string { func (*ThunkDir) ProtoMessage() {} func (x *ThunkDir) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[13] + mi := &file_bass_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1339,7 +1208,7 @@ func (x *ThunkDir) ProtoReflect() protoreflect.Message { // Deprecated: Use ThunkDir.ProtoReflect.Descriptor instead. func (*ThunkDir) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{13} + return file_bass_proto_rawDescGZIP(), []int{12} } func (m *ThunkDir) GetDir() isThunkDir_Dir { @@ -1410,7 +1279,7 @@ type ThunkMountSource struct { func (x *ThunkMountSource) Reset() { *x = ThunkMountSource{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[14] + mi := &file_bass_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1423,7 +1292,7 @@ func (x *ThunkMountSource) String() string { func (*ThunkMountSource) ProtoMessage() {} func (x *ThunkMountSource) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[14] + mi := &file_bass_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1436,7 +1305,7 @@ func (x *ThunkMountSource) ProtoReflect() protoreflect.Message { // Deprecated: Use ThunkMountSource.ProtoReflect.Descriptor instead. func (*ThunkMountSource) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{14} + return file_bass_proto_rawDescGZIP(), []int{13} } func (m *ThunkMountSource) GetSource() isThunkMountSource_Source { @@ -1527,7 +1396,7 @@ type ThunkMount struct { func (x *ThunkMount) Reset() { *x = ThunkMount{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[15] + mi := &file_bass_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1540,7 +1409,7 @@ func (x *ThunkMount) String() string { func (*ThunkMount) ProtoMessage() {} func (x *ThunkMount) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[15] + mi := &file_bass_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1553,7 +1422,7 @@ func (x *ThunkMount) ProtoReflect() protoreflect.Message { // Deprecated: Use ThunkMount.ProtoReflect.Descriptor instead. func (*ThunkMount) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{15} + return file_bass_proto_rawDescGZIP(), []int{14} } func (x *ThunkMount) GetSource() *ThunkMountSource { @@ -1581,7 +1450,7 @@ type Array struct { func (x *Array) Reset() { *x = Array{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[16] + mi := &file_bass_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1594,7 +1463,7 @@ func (x *Array) String() string { func (*Array) ProtoMessage() {} func (x *Array) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[16] + mi := &file_bass_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1607,7 +1476,7 @@ func (x *Array) ProtoReflect() protoreflect.Message { // Deprecated: Use Array.ProtoReflect.Descriptor instead. func (*Array) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{16} + return file_bass_proto_rawDescGZIP(), []int{15} } func (x *Array) GetValues() []*Value { @@ -1628,7 +1497,7 @@ type Object struct { func (x *Object) Reset() { *x = Object{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[17] + mi := &file_bass_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1641,7 +1510,7 @@ func (x *Object) String() string { func (*Object) ProtoMessage() {} func (x *Object) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[17] + mi := &file_bass_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1654,7 +1523,7 @@ func (x *Object) ProtoReflect() protoreflect.Message { // Deprecated: Use Object.ProtoReflect.Descriptor instead. func (*Object) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{17} + return file_bass_proto_rawDescGZIP(), []int{16} } func (x *Object) GetBindings() []*Binding { @@ -1676,7 +1545,7 @@ type Binding struct { func (x *Binding) Reset() { *x = Binding{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[18] + mi := &file_bass_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1689,7 +1558,7 @@ func (x *Binding) String() string { func (*Binding) ProtoMessage() {} func (x *Binding) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[18] + mi := &file_bass_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1702,7 +1571,7 @@ func (x *Binding) ProtoReflect() protoreflect.Message { // Deprecated: Use Binding.ProtoReflect.Descriptor instead. func (*Binding) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{18} + return file_bass_proto_rawDescGZIP(), []int{17} } func (x *Binding) GetSymbol() string { @@ -1728,7 +1597,7 @@ type Null struct { func (x *Null) Reset() { *x = Null{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[19] + mi := &file_bass_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1741,7 +1610,7 @@ func (x *Null) String() string { func (*Null) ProtoMessage() {} func (x *Null) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[19] + mi := &file_bass_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1754,7 +1623,7 @@ func (x *Null) ProtoReflect() protoreflect.Message { // Deprecated: Use Null.ProtoReflect.Descriptor instead. func (*Null) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{19} + return file_bass_proto_rawDescGZIP(), []int{18} } type Bool struct { @@ -1768,7 +1637,7 @@ type Bool struct { func (x *Bool) Reset() { *x = Bool{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[20] + mi := &file_bass_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1781,7 +1650,7 @@ func (x *Bool) String() string { func (*Bool) ProtoMessage() {} func (x *Bool) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[20] + mi := &file_bass_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1794,7 +1663,7 @@ func (x *Bool) ProtoReflect() protoreflect.Message { // Deprecated: Use Bool.ProtoReflect.Descriptor instead. func (*Bool) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{20} + return file_bass_proto_rawDescGZIP(), []int{19} } func (x *Bool) GetValue() bool { @@ -1815,7 +1684,7 @@ type Int struct { func (x *Int) Reset() { *x = Int{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[21] + mi := &file_bass_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1828,7 +1697,7 @@ func (x *Int) String() string { func (*Int) ProtoMessage() {} func (x *Int) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[21] + mi := &file_bass_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1841,7 +1710,7 @@ func (x *Int) ProtoReflect() protoreflect.Message { // Deprecated: Use Int.ProtoReflect.Descriptor instead. func (*Int) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{21} + return file_bass_proto_rawDescGZIP(), []int{20} } func (x *Int) GetValue() int64 { @@ -1862,7 +1731,7 @@ type String struct { func (x *String) Reset() { *x = String{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[22] + mi := &file_bass_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1875,7 +1744,7 @@ func (x *String) String() string { func (*String) ProtoMessage() {} func (x *String) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[22] + mi := &file_bass_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1888,7 +1757,7 @@ func (x *String) ProtoReflect() protoreflect.Message { // Deprecated: Use String.ProtoReflect.Descriptor instead. func (*String) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{22} + return file_bass_proto_rawDescGZIP(), []int{21} } func (x *String) GetValue() string { @@ -1910,7 +1779,7 @@ type CachePath struct { func (x *CachePath) Reset() { *x = CachePath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[23] + mi := &file_bass_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1923,7 +1792,7 @@ func (x *CachePath) String() string { func (*CachePath) ProtoMessage() {} func (x *CachePath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[23] + mi := &file_bass_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1936,7 +1805,7 @@ func (x *CachePath) ProtoReflect() protoreflect.Message { // Deprecated: Use CachePath.ProtoReflect.Descriptor instead. func (*CachePath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{23} + return file_bass_proto_rawDescGZIP(), []int{22} } func (x *CachePath) GetId() string { @@ -1964,7 +1833,7 @@ type Secret struct { func (x *Secret) Reset() { *x = Secret{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[24] + mi := &file_bass_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1977,7 +1846,7 @@ func (x *Secret) String() string { func (*Secret) ProtoMessage() {} func (x *Secret) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[24] + mi := &file_bass_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1990,7 +1859,7 @@ func (x *Secret) ProtoReflect() protoreflect.Message { // Deprecated: Use Secret.ProtoReflect.Descriptor instead. func (*Secret) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{24} + return file_bass_proto_rawDescGZIP(), []int{23} } func (x *Secret) GetName() string { @@ -2011,7 +1880,7 @@ type CommandPath struct { func (x *CommandPath) Reset() { *x = CommandPath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[25] + mi := &file_bass_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2024,7 +1893,7 @@ func (x *CommandPath) String() string { func (*CommandPath) ProtoMessage() {} func (x *CommandPath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[25] + mi := &file_bass_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2037,7 +1906,7 @@ func (x *CommandPath) ProtoReflect() protoreflect.Message { // Deprecated: Use CommandPath.ProtoReflect.Descriptor instead. func (*CommandPath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{25} + return file_bass_proto_rawDescGZIP(), []int{24} } func (x *CommandPath) GetName() string { @@ -2058,7 +1927,7 @@ type FilePath struct { func (x *FilePath) Reset() { *x = FilePath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[26] + mi := &file_bass_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2071,7 +1940,7 @@ func (x *FilePath) String() string { func (*FilePath) ProtoMessage() {} func (x *FilePath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[26] + mi := &file_bass_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2084,7 +1953,7 @@ func (x *FilePath) ProtoReflect() protoreflect.Message { // Deprecated: Use FilePath.ProtoReflect.Descriptor instead. func (*FilePath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{26} + return file_bass_proto_rawDescGZIP(), []int{25} } func (x *FilePath) GetPath() string { @@ -2105,7 +1974,7 @@ type DirPath struct { func (x *DirPath) Reset() { *x = DirPath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[27] + mi := &file_bass_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2118,7 +1987,7 @@ func (x *DirPath) String() string { func (*DirPath) ProtoMessage() {} func (x *DirPath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[27] + mi := &file_bass_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2131,7 +2000,7 @@ func (x *DirPath) ProtoReflect() protoreflect.Message { // Deprecated: Use DirPath.ProtoReflect.Descriptor instead. func (*DirPath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{27} + return file_bass_proto_rawDescGZIP(), []int{26} } func (x *DirPath) GetPath() string { @@ -2156,7 +2025,7 @@ type FilesystemPath struct { func (x *FilesystemPath) Reset() { *x = FilesystemPath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[28] + mi := &file_bass_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2169,7 +2038,7 @@ func (x *FilesystemPath) String() string { func (*FilesystemPath) ProtoMessage() {} func (x *FilesystemPath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[28] + mi := &file_bass_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2182,7 +2051,7 @@ func (x *FilesystemPath) ProtoReflect() protoreflect.Message { // Deprecated: Use FilesystemPath.ProtoReflect.Descriptor instead. func (*FilesystemPath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{28} + return file_bass_proto_rawDescGZIP(), []int{27} } func (m *FilesystemPath) GetPath() isFilesystemPath_Path { @@ -2234,7 +2103,7 @@ type ThunkPath struct { func (x *ThunkPath) Reset() { *x = ThunkPath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[29] + mi := &file_bass_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2247,7 +2116,7 @@ func (x *ThunkPath) String() string { func (*ThunkPath) ProtoMessage() {} func (x *ThunkPath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[29] + mi := &file_bass_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2260,7 +2129,7 @@ func (x *ThunkPath) ProtoReflect() protoreflect.Message { // Deprecated: Use ThunkPath.ProtoReflect.Descriptor instead. func (*ThunkPath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{29} + return file_bass_proto_rawDescGZIP(), []int{28} } func (x *ThunkPath) GetThunk() *Thunk { @@ -2289,7 +2158,7 @@ type HostPath struct { func (x *HostPath) Reset() { *x = HostPath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[30] + mi := &file_bass_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2302,7 +2171,7 @@ func (x *HostPath) String() string { func (*HostPath) ProtoMessage() {} func (x *HostPath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[30] + mi := &file_bass_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2315,7 +2184,7 @@ func (x *HostPath) ProtoReflect() protoreflect.Message { // Deprecated: Use HostPath.ProtoReflect.Descriptor instead. func (*HostPath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{30} + return file_bass_proto_rawDescGZIP(), []int{29} } func (x *HostPath) GetContext() string { @@ -2347,7 +2216,7 @@ type LogicalPath struct { func (x *LogicalPath) Reset() { *x = LogicalPath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[31] + mi := &file_bass_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2360,7 +2229,7 @@ func (x *LogicalPath) String() string { func (*LogicalPath) ProtoMessage() {} func (x *LogicalPath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[31] + mi := &file_bass_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2373,7 +2242,7 @@ func (x *LogicalPath) ProtoReflect() protoreflect.Message { // Deprecated: Use LogicalPath.ProtoReflect.Descriptor instead. func (*LogicalPath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{31} + return file_bass_proto_rawDescGZIP(), []int{30} } func (m *LogicalPath) GetPath() isLogicalPath_Path { @@ -2425,7 +2294,7 @@ type LogicalPath_File struct { func (x *LogicalPath_File) Reset() { *x = LogicalPath_File{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[32] + mi := &file_bass_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2438,7 +2307,7 @@ func (x *LogicalPath_File) String() string { func (*LogicalPath_File) ProtoMessage() {} func (x *LogicalPath_File) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[32] + mi := &file_bass_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2451,7 +2320,7 @@ func (x *LogicalPath_File) ProtoReflect() protoreflect.Message { // Deprecated: Use LogicalPath_File.ProtoReflect.Descriptor instead. func (*LogicalPath_File) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{31, 0} + return file_bass_proto_rawDescGZIP(), []int{30, 0} } func (x *LogicalPath_File) GetName() string { @@ -2480,7 +2349,7 @@ type LogicalPath_Dir struct { func (x *LogicalPath_Dir) Reset() { *x = LogicalPath_Dir{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[33] + mi := &file_bass_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2493,7 +2362,7 @@ func (x *LogicalPath_Dir) String() string { func (*LogicalPath_Dir) ProtoMessage() {} func (x *LogicalPath_Dir) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[33] + mi := &file_bass_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2506,7 +2375,7 @@ func (x *LogicalPath_Dir) ProtoReflect() protoreflect.Message { // Deprecated: Use LogicalPath_Dir.ProtoReflect.Descriptor instead. func (*LogicalPath_Dir) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{31, 1} + return file_bass_proto_rawDescGZIP(), []int{30, 1} } func (x *LogicalPath_Dir) GetName() string { @@ -2527,7 +2396,7 @@ var File_bass_proto protoreflect.FileDescriptor var file_bass_proto_rawDesc = []byte{ 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x62, 0x61, - 0x73, 0x73, 0x22, 0x93, 0x05, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x20, 0x0a, 0x04, + 0x73, 0x73, 0x22, 0xc5, 0x05, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x20, 0x0a, 0x04, 0x6e, 0x75, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4e, 0x75, 0x6c, 0x6c, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x75, 0x6c, 0x6c, 0x12, 0x20, 0x0a, 0x04, 0x62, 0x6f, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x62, @@ -2567,15 +2436,16 @@ var file_bass_proto_rawDesc = []byte{ 0x52, 0x0b, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x30, 0x0a, 0x0a, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x41, 0x64, - 0x64, 0x72, 0x48, 0x00, 0x52, 0x09, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x42, - 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x8e, 0x03, 0x0a, 0x05, 0x54, 0x68, 0x75, - 0x6e, 0x6b, 0x12, 0x26, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x10, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x49, 0x6d, - 0x61, 0x67, 0x65, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x6e, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12, 0x20, 0x0a, 0x03, 0x63, 0x6d, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, - 0x43, 0x6d, 0x64, 0x52, 0x03, 0x63, 0x6d, 0x64, 0x12, 0x1f, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, + 0x64, 0x72, 0x48, 0x00, 0x52, 0x09, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x12, + 0x30, 0x0a, 0x0a, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x10, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, + 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x63, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, + 0x68, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xec, 0x02, 0x0a, 0x05, 0x54, + 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x26, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, + 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, + 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, + 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12, 0x1f, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x21, 0x0a, 0x05, 0x73, 0x74, 0x64, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, @@ -2675,24 +2545,7 @@ var file_bass_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2e, 0x0a, 0x08, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x6f, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x22, 0x8d, 0x02, 0x0a, 0x08, - 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x43, 0x6d, 0x64, 0x12, 0x2d, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x61, 0x73, 0x73, - 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x07, - 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x24, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, - 0x65, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x27, 0x0a, - 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, - 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, - 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x48, 0x6f, 0x73, 0x74, - 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x07, - 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, - 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, - 0x48, 0x00, 0x52, 0x07, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x05, 0x63, - 0x61, 0x63, 0x68, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, - 0x73, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x63, - 0x61, 0x63, 0x68, 0x65, 0x42, 0x05, 0x0a, 0x03, 0x63, 0x6d, 0x64, 0x22, 0x87, 0x01, 0x0a, 0x08, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x22, 0x87, 0x01, 0x0a, 0x08, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x44, 0x69, 0x72, 0x12, 0x25, 0x0a, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x44, 0x69, 0x72, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x12, @@ -2800,7 +2653,7 @@ func file_bass_proto_rawDescGZIP() []byte { return file_bass_proto_rawDescData } -var file_bass_proto_msgTypes = make([]protoimpl.MessageInfo, 34) +var file_bass_proto_msgTypes = make([]protoimpl.MessageInfo, 33) var file_bass_proto_goTypes = []interface{}{ (*Value)(nil), // 0: bass.Value (*Thunk)(nil), // 1: bass.Thunk @@ -2814,106 +2667,99 @@ var file_bass_proto_goTypes = []interface{}{ (*ImageBuildInput)(nil), // 9: bass.ImageBuildInput (*BuildArg)(nil), // 10: bass.BuildArg (*Platform)(nil), // 11: bass.Platform - (*ThunkCmd)(nil), // 12: bass.ThunkCmd - (*ThunkDir)(nil), // 13: bass.ThunkDir - (*ThunkMountSource)(nil), // 14: bass.ThunkMountSource - (*ThunkMount)(nil), // 15: bass.ThunkMount - (*Array)(nil), // 16: bass.Array - (*Object)(nil), // 17: bass.Object - (*Binding)(nil), // 18: bass.Binding - (*Null)(nil), // 19: bass.Null - (*Bool)(nil), // 20: bass.Bool - (*Int)(nil), // 21: bass.Int - (*String)(nil), // 22: bass.String - (*CachePath)(nil), // 23: bass.CachePath - (*Secret)(nil), // 24: bass.Secret - (*CommandPath)(nil), // 25: bass.CommandPath - (*FilePath)(nil), // 26: bass.FilePath - (*DirPath)(nil), // 27: bass.DirPath - (*FilesystemPath)(nil), // 28: bass.FilesystemPath - (*ThunkPath)(nil), // 29: bass.ThunkPath - (*HostPath)(nil), // 30: bass.HostPath - (*LogicalPath)(nil), // 31: bass.LogicalPath - (*LogicalPath_File)(nil), // 32: bass.LogicalPath.File - (*LogicalPath_Dir)(nil), // 33: bass.LogicalPath.Dir + (*ThunkDir)(nil), // 12: bass.ThunkDir + (*ThunkMountSource)(nil), // 13: bass.ThunkMountSource + (*ThunkMount)(nil), // 14: bass.ThunkMount + (*Array)(nil), // 15: bass.Array + (*Object)(nil), // 16: bass.Object + (*Binding)(nil), // 17: bass.Binding + (*Null)(nil), // 18: bass.Null + (*Bool)(nil), // 19: bass.Bool + (*Int)(nil), // 20: bass.Int + (*String)(nil), // 21: bass.String + (*CachePath)(nil), // 22: bass.CachePath + (*Secret)(nil), // 23: bass.Secret + (*CommandPath)(nil), // 24: bass.CommandPath + (*FilePath)(nil), // 25: bass.FilePath + (*DirPath)(nil), // 26: bass.DirPath + (*FilesystemPath)(nil), // 27: bass.FilesystemPath + (*ThunkPath)(nil), // 28: bass.ThunkPath + (*HostPath)(nil), // 29: bass.HostPath + (*LogicalPath)(nil), // 30: bass.LogicalPath + (*LogicalPath_File)(nil), // 31: bass.LogicalPath.File + (*LogicalPath_Dir)(nil), // 32: bass.LogicalPath.Dir } var file_bass_proto_depIdxs = []int32{ - 19, // 0: bass.Value.null:type_name -> bass.Null - 20, // 1: bass.Value.bool:type_name -> bass.Bool - 21, // 2: bass.Value.int:type_name -> bass.Int - 22, // 3: bass.Value.string:type_name -> bass.String - 24, // 4: bass.Value.secret:type_name -> bass.Secret - 16, // 5: bass.Value.array:type_name -> bass.Array - 17, // 6: bass.Value.object:type_name -> bass.Object + 18, // 0: bass.Value.null:type_name -> bass.Null + 19, // 1: bass.Value.bool:type_name -> bass.Bool + 20, // 2: bass.Value.int:type_name -> bass.Int + 21, // 3: bass.Value.string:type_name -> bass.String + 23, // 4: bass.Value.secret:type_name -> bass.Secret + 15, // 5: bass.Value.array:type_name -> bass.Array + 16, // 6: bass.Value.object:type_name -> bass.Object 1, // 7: bass.Value.thunk:type_name -> bass.Thunk - 25, // 8: bass.Value.command_path:type_name -> bass.CommandPath - 26, // 9: bass.Value.file_path:type_name -> bass.FilePath - 27, // 10: bass.Value.dir_path:type_name -> bass.DirPath - 30, // 11: bass.Value.host_path:type_name -> bass.HostPath - 29, // 12: bass.Value.thunk_path:type_name -> bass.ThunkPath - 31, // 13: bass.Value.logical_path:type_name -> bass.LogicalPath + 24, // 8: bass.Value.command_path:type_name -> bass.CommandPath + 25, // 9: bass.Value.file_path:type_name -> bass.FilePath + 26, // 10: bass.Value.dir_path:type_name -> bass.DirPath + 29, // 11: bass.Value.host_path:type_name -> bass.HostPath + 28, // 12: bass.Value.thunk_path:type_name -> bass.ThunkPath + 30, // 13: bass.Value.logical_path:type_name -> bass.LogicalPath 2, // 14: bass.Value.thunk_addr:type_name -> bass.ThunkAddr - 5, // 15: bass.Thunk.image:type_name -> bass.ThunkImage - 12, // 16: bass.Thunk.cmd:type_name -> bass.ThunkCmd + 22, // 15: bass.Value.cache_path:type_name -> bass.CachePath + 5, // 16: bass.Thunk.image:type_name -> bass.ThunkImage 0, // 17: bass.Thunk.args:type_name -> bass.Value 0, // 18: bass.Thunk.stdin:type_name -> bass.Value - 18, // 19: bass.Thunk.env:type_name -> bass.Binding - 13, // 20: bass.Thunk.dir:type_name -> bass.ThunkDir - 15, // 21: bass.Thunk.mounts:type_name -> bass.ThunkMount - 18, // 22: bass.Thunk.labels:type_name -> bass.Binding + 17, // 19: bass.Thunk.env:type_name -> bass.Binding + 12, // 20: bass.Thunk.dir:type_name -> bass.ThunkDir + 14, // 21: bass.Thunk.mounts:type_name -> bass.ThunkMount + 17, // 22: bass.Thunk.labels:type_name -> bass.Binding 3, // 23: bass.Thunk.ports:type_name -> bass.ThunkPort 4, // 24: bass.Thunk.tls:type_name -> bass.ThunkTLS 1, // 25: bass.ThunkAddr.thunk:type_name -> bass.Thunk - 26, // 26: bass.ThunkTLS.cert:type_name -> bass.FilePath - 26, // 27: bass.ThunkTLS.key:type_name -> bass.FilePath + 25, // 26: bass.ThunkTLS.cert:type_name -> bass.FilePath + 25, // 27: bass.ThunkTLS.key:type_name -> bass.FilePath 6, // 28: bass.ThunkImage.ref:type_name -> bass.ImageRef 1, // 29: bass.ThunkImage.thunk:type_name -> bass.Thunk 7, // 30: bass.ThunkImage.archive:type_name -> bass.ImageArchive 8, // 31: bass.ThunkImage.docker_build:type_name -> bass.ImageDockerBuild 11, // 32: bass.ImageRef.platform:type_name -> bass.Platform - 29, // 33: bass.ImageRef.file:type_name -> bass.ThunkPath + 28, // 33: bass.ImageRef.file:type_name -> bass.ThunkPath 2, // 34: bass.ImageRef.addr:type_name -> bass.ThunkAddr 11, // 35: bass.ImageArchive.platform:type_name -> bass.Platform - 29, // 36: bass.ImageArchive.file:type_name -> bass.ThunkPath + 28, // 36: bass.ImageArchive.file:type_name -> bass.ThunkPath 11, // 37: bass.ImageDockerBuild.platform:type_name -> bass.Platform 9, // 38: bass.ImageDockerBuild.context:type_name -> bass.ImageBuildInput 10, // 39: bass.ImageDockerBuild.args:type_name -> bass.BuildArg - 29, // 40: bass.ImageBuildInput.thunk:type_name -> bass.ThunkPath - 30, // 41: bass.ImageBuildInput.host:type_name -> bass.HostPath - 31, // 42: bass.ImageBuildInput.logical:type_name -> bass.LogicalPath - 25, // 43: bass.ThunkCmd.command:type_name -> bass.CommandPath - 26, // 44: bass.ThunkCmd.file:type_name -> bass.FilePath - 29, // 45: bass.ThunkCmd.thunk:type_name -> bass.ThunkPath - 30, // 46: bass.ThunkCmd.host:type_name -> bass.HostPath - 31, // 47: bass.ThunkCmd.logical:type_name -> bass.LogicalPath - 23, // 48: bass.ThunkCmd.cache:type_name -> bass.CachePath - 27, // 49: bass.ThunkDir.local:type_name -> bass.DirPath - 29, // 50: bass.ThunkDir.thunk:type_name -> bass.ThunkPath - 30, // 51: bass.ThunkDir.host:type_name -> bass.HostPath - 29, // 52: bass.ThunkMountSource.thunk:type_name -> bass.ThunkPath - 30, // 53: bass.ThunkMountSource.host:type_name -> bass.HostPath - 31, // 54: bass.ThunkMountSource.logical:type_name -> bass.LogicalPath - 23, // 55: bass.ThunkMountSource.cache:type_name -> bass.CachePath - 24, // 56: bass.ThunkMountSource.secret:type_name -> bass.Secret - 14, // 57: bass.ThunkMount.source:type_name -> bass.ThunkMountSource - 28, // 58: bass.ThunkMount.target:type_name -> bass.FilesystemPath - 0, // 59: bass.Array.values:type_name -> bass.Value - 18, // 60: bass.Object.bindings:type_name -> bass.Binding - 0, // 61: bass.Binding.value:type_name -> bass.Value - 28, // 62: bass.CachePath.path:type_name -> bass.FilesystemPath - 26, // 63: bass.FilesystemPath.file:type_name -> bass.FilePath - 27, // 64: bass.FilesystemPath.dir:type_name -> bass.DirPath - 1, // 65: bass.ThunkPath.thunk:type_name -> bass.Thunk - 28, // 66: bass.ThunkPath.path:type_name -> bass.FilesystemPath - 28, // 67: bass.HostPath.path:type_name -> bass.FilesystemPath - 32, // 68: bass.LogicalPath.file:type_name -> bass.LogicalPath.File - 33, // 69: bass.LogicalPath.dir:type_name -> bass.LogicalPath.Dir - 31, // 70: bass.LogicalPath.Dir.entries:type_name -> bass.LogicalPath - 71, // [71:71] is the sub-list for method output_type - 71, // [71:71] is the sub-list for method input_type - 71, // [71:71] is the sub-list for extension type_name - 71, // [71:71] is the sub-list for extension extendee - 0, // [0:71] is the sub-list for field type_name + 28, // 40: bass.ImageBuildInput.thunk:type_name -> bass.ThunkPath + 29, // 41: bass.ImageBuildInput.host:type_name -> bass.HostPath + 30, // 42: bass.ImageBuildInput.logical:type_name -> bass.LogicalPath + 26, // 43: bass.ThunkDir.local:type_name -> bass.DirPath + 28, // 44: bass.ThunkDir.thunk:type_name -> bass.ThunkPath + 29, // 45: bass.ThunkDir.host:type_name -> bass.HostPath + 28, // 46: bass.ThunkMountSource.thunk:type_name -> bass.ThunkPath + 29, // 47: bass.ThunkMountSource.host:type_name -> bass.HostPath + 30, // 48: bass.ThunkMountSource.logical:type_name -> bass.LogicalPath + 22, // 49: bass.ThunkMountSource.cache:type_name -> bass.CachePath + 23, // 50: bass.ThunkMountSource.secret:type_name -> bass.Secret + 13, // 51: bass.ThunkMount.source:type_name -> bass.ThunkMountSource + 27, // 52: bass.ThunkMount.target:type_name -> bass.FilesystemPath + 0, // 53: bass.Array.values:type_name -> bass.Value + 17, // 54: bass.Object.bindings:type_name -> bass.Binding + 0, // 55: bass.Binding.value:type_name -> bass.Value + 27, // 56: bass.CachePath.path:type_name -> bass.FilesystemPath + 25, // 57: bass.FilesystemPath.file:type_name -> bass.FilePath + 26, // 58: bass.FilesystemPath.dir:type_name -> bass.DirPath + 1, // 59: bass.ThunkPath.thunk:type_name -> bass.Thunk + 27, // 60: bass.ThunkPath.path:type_name -> bass.FilesystemPath + 27, // 61: bass.HostPath.path:type_name -> bass.FilesystemPath + 31, // 62: bass.LogicalPath.file:type_name -> bass.LogicalPath.File + 32, // 63: bass.LogicalPath.dir:type_name -> bass.LogicalPath.Dir + 30, // 64: bass.LogicalPath.Dir.entries:type_name -> bass.LogicalPath + 65, // [65:65] is the sub-list for method output_type + 65, // [65:65] is the sub-list for method input_type + 65, // [65:65] is the sub-list for extension type_name + 65, // [65:65] is the sub-list for extension extendee + 0, // [0:65] is the sub-list for field type_name } func init() { file_bass_proto_init() } @@ -3067,18 +2913,6 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ThunkCmd); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_bass_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ThunkDir); i { case 0: return &v.state @@ -3090,7 +2924,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ThunkMountSource); i { case 0: return &v.state @@ -3102,7 +2936,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ThunkMount); i { case 0: return &v.state @@ -3114,7 +2948,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Array); i { case 0: return &v.state @@ -3126,7 +2960,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Object); i { case 0: return &v.state @@ -3138,7 +2972,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Binding); i { case 0: return &v.state @@ -3150,7 +2984,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Null); i { case 0: return &v.state @@ -3162,7 +2996,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Bool); i { case 0: return &v.state @@ -3174,7 +3008,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Int); i { case 0: return &v.state @@ -3186,7 +3020,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*String); i { case 0: return &v.state @@ -3198,7 +3032,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CachePath); i { case 0: return &v.state @@ -3210,7 +3044,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Secret); i { case 0: return &v.state @@ -3222,7 +3056,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CommandPath); i { case 0: return &v.state @@ -3234,7 +3068,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FilePath); i { case 0: return &v.state @@ -3246,7 +3080,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DirPath); i { case 0: return &v.state @@ -3258,7 +3092,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FilesystemPath); i { case 0: return &v.state @@ -3270,7 +3104,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ThunkPath); i { case 0: return &v.state @@ -3282,7 +3116,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HostPath); i { case 0: return &v.state @@ -3294,7 +3128,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*LogicalPath); i { case 0: return &v.state @@ -3306,7 +3140,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*LogicalPath_File); i { case 0: return &v.state @@ -3318,7 +3152,7 @@ func file_bass_proto_init() { return nil } } - file_bass_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + file_bass_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*LogicalPath_Dir); i { case 0: return &v.state @@ -3347,6 +3181,7 @@ func file_bass_proto_init() { (*Value_ThunkPath)(nil), (*Value_LogicalPath)(nil), (*Value_ThunkAddr)(nil), + (*Value_CachePath)(nil), } file_bass_proto_msgTypes[5].OneofWrappers = []interface{}{ (*ThunkImage_Ref)(nil), @@ -3367,30 +3202,22 @@ func file_bass_proto_init() { (*ImageBuildInput_Logical)(nil), } file_bass_proto_msgTypes[12].OneofWrappers = []interface{}{ - (*ThunkCmd_Command)(nil), - (*ThunkCmd_File)(nil), - (*ThunkCmd_Thunk)(nil), - (*ThunkCmd_Host)(nil), - (*ThunkCmd_Logical)(nil), - (*ThunkCmd_Cache)(nil), - } - file_bass_proto_msgTypes[13].OneofWrappers = []interface{}{ (*ThunkDir_Local)(nil), (*ThunkDir_Thunk)(nil), (*ThunkDir_Host)(nil), } - file_bass_proto_msgTypes[14].OneofWrappers = []interface{}{ + file_bass_proto_msgTypes[13].OneofWrappers = []interface{}{ (*ThunkMountSource_Thunk)(nil), (*ThunkMountSource_Host)(nil), (*ThunkMountSource_Logical)(nil), (*ThunkMountSource_Cache)(nil), (*ThunkMountSource_Secret)(nil), } - file_bass_proto_msgTypes[28].OneofWrappers = []interface{}{ + file_bass_proto_msgTypes[27].OneofWrappers = []interface{}{ (*FilesystemPath_File)(nil), (*FilesystemPath_Dir)(nil), } - file_bass_proto_msgTypes[31].OneofWrappers = []interface{}{ + file_bass_proto_msgTypes[30].OneofWrappers = []interface{}{ (*LogicalPath_File_)(nil), (*LogicalPath_Dir_)(nil), } @@ -3400,7 +3227,7 @@ func file_bass_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_bass_proto_rawDesc, NumEnums: 0, - NumMessages: 34, + NumMessages: 33, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/proto/value.go b/pkg/proto/value.go index beb5bf9f..d7308a5f 100644 --- a/pkg/proto/value.go +++ b/pkg/proto/value.go @@ -30,6 +30,8 @@ func NewValue(msg Message) (*Value, error) { val.Value = &Value_Thunk{x} case *ThunkPath: val.Value = &Value_ThunkPath{x} + case *CachePath: + val.Value = &Value_CachePath{x} case *CommandPath: val.Value = &Value_CommandPath{x} case *Null: diff --git a/pkg/runtimes/buildkit.go b/pkg/runtimes/buildkit.go index 7a097ae1..a9a5e937 100644 --- a/pkg/runtimes/buildkit.go +++ b/pkg/runtimes/buildkit.go @@ -262,7 +262,7 @@ func (runtime *Buildkit) Run(ctx context.Context, thunk bass.Thunk) error { _, err := runtime.build( ctx, thunk, - func(st llb.ExecState, _ string) marshalable { + func(st llb.ExecState, _ string) llb.State { return st.GetMount(ioDir) }, nil, // exports @@ -290,7 +290,7 @@ func (runtime *Buildkit) Start(ctx context.Context, thunk bass.Thunk) (StartResu _, err := runtime.build( ctx, thunk, - func(st llb.ExecState, _ string) marshalable { + func(st llb.ExecState, _ string) llb.State { return st.GetMount(ioDir) }, nil, // exports @@ -345,7 +345,7 @@ func (runtime *Buildkit) Read(ctx context.Context, w io.Writer, thunk bass.Thunk _, err = runtime.build( ctx, thunk, - func(st llb.ExecState, _ string) marshalable { + func(st llb.ExecState, _ string) llb.State { return st.GetMount(ioDir) }, []kitdclient.ExportEntry{ @@ -383,7 +383,9 @@ func (runtime *Buildkit) Export(ctx context.Context, w io.Writer, thunk bass.Thu _, err := runtime.build( ctx, thunk, - func(st llb.ExecState, _ string) marshalable { return st }, + func(st llb.ExecState, _ string) llb.State { + return st.Root() + }, []kitdclient.ExportEntry{ { Type: kitdclient.ExporterOCI, @@ -408,7 +410,9 @@ func (runtime *Buildkit) Publish(ctx context.Context, ref bass.ImageRef, thunk b res, err := runtime.build( ctx, thunk, - func(st llb.ExecState, _ string) marshalable { return st }, + func(st llb.ExecState, _ string) llb.State { + return st.Root() + }, []kitdclient.ExportEntry{ { Type: kitdclient.ExporterImage, @@ -441,7 +445,7 @@ func (runtime *Buildkit) ExportPath(ctx context.Context, w io.Writer, tp bass.Th _, err := runtime.build( ctx, thunk, - func(st llb.ExecState, sp string) marshalable { + func(st llb.ExecState, sp string) llb.State { copyOpt := &llb.CopyInfo{} if path.FilesystemPath().IsDir() { copyOpt.CopyDirContentsOnly = true @@ -518,13 +522,14 @@ func (runtime *Buildkit) Close() error { func (runtime *Buildkit) build( ctx context.Context, thunk bass.Thunk, - transform func(llb.ExecState, string) marshalable, + transform func(llb.ExecState, string) llb.State, exports []kitdclient.ExportEntry, runOpts ...llb.RunOption, ) (*kitdclient.SolveResponse, error) { var def *llb.Definition var secrets map[string][]byte var localDirs map[string]string + var imageConfig ocispecs.ImageConfig var allowed []entitlements.Entitlement statusProxy := forwardStatus(progrock.RecorderFromContext(ctx)) @@ -536,19 +541,20 @@ func (runtime *Buildkit) build( }, buildkitProduct, func(ctx context.Context, gw gwclient.Client) (*gwclient.Result, error) { b := runtime.newBuilder(ctx, gw) - st, sp, needsInsecure, err := b.llb(ctx, thunk, runOpts...) + ib, err := b.llb(ctx, thunk, transform, runOpts...) if err != nil { return nil, err } - if needsInsecure { + if ib.needsInsecure { allowed = append(allowed, entitlements.EntitlementSecurityInsecure) } localDirs = b.localDirs secrets = b.secrets + imageConfig = ib.config - def, err = transform(st, sp).Marshal(ctx) + def, err = ib.output.Marshal(ctx) if err != nil { return nil, err } @@ -559,7 +565,7 @@ func (runtime *Buildkit) build( return nil, statusProxy.NiceError("llb build failed", err) } - res, err := runtime.Client.Solve(ctx, def, kitdclient.SolveOpt{ + res, err := runtime.Client.Build(ctx, kitdclient.SolveOpt{ LocalDirs: localDirs, AllowedEntitlements: allowed, Session: []session.Attachable{ @@ -570,6 +576,28 @@ func (runtime *Buildkit) build( OCIStores: map[string]content.Store{ ociStoreName: runtime.ociStore, }, + }, buildkitProduct, func(ctx context.Context, gw gwclient.Client) (*gwclient.Result, error) { + res, err := gw.Solve(ctx, gwclient.SolveRequest{ + Evaluate: true, + Definition: def.ToPB(), + }) + if err != nil { + return nil, err + } + + cfgBytes, err := json.Marshal(ocispecs.Image{ + Architecture: runtime.Platform.Architecture, + OS: runtime.Platform.OS, + OSVersion: runtime.Platform.OSVersion, + OSFeatures: runtime.Platform.OSFeatures, + Config: imageConfig, + }) + if err != nil { + return nil, err + } + res.AddMeta(exptypes.ExporterImageConfigKey, cfgBytes) + + return res, nil }, statusProxy.Writer()) if err != nil { return nil, statusProxy.NiceError("build failed", err) @@ -711,41 +739,48 @@ func (runtime *Buildkit) newBuilder(ctx context.Context, resolver llb.ImageMetaR } } -func (b *buildkitBuilder) llb(ctx context.Context, thunk bass.Thunk, extraOpts ...llb.RunOption) (llb.ExecState, string, bool, error) { - cmd, err := NewCommand(ctx, b.runtime, thunk) +func (b *buildkitBuilder) llb( + ctx context.Context, + thunk bass.Thunk, + transform func(llb.ExecState, string) llb.State, + extraOpts ...llb.RunOption, +) (intermediateBuild, error) { + ib, err := b.image(ctx, thunk.Image) if err != nil { - return llb.ExecState{}, "", false, err + return ib, err } - imageRef, runState, sourcePath, needsInsecure, err := b.image(ctx, thunk.Image) + thunkName, err := thunk.Hash() if err != nil { - return llb.ExecState{}, "", false, err + return ib, err } - id, err := thunk.Hash() + cmd, err := NewCommand(ctx, b.runtime, thunk) if err != nil { - return llb.ExecState{}, "", false, err + return ib, err } + cmd.Args = append(ib.config.Entrypoint, cmd.Args...) + cmdPayload, err := bass.MarshalJSON(cmd) if err != nil { - return llb.ExecState{}, "", false, err + return ib, err } shimExe, err := b.runtime.shim() if err != nil { - return llb.ExecState{}, "", false, err + return ib, err } rootCA, err := os.ReadFile(basstls.CACert(b.runtime.Config.CertsDir)) if err != nil { - return llb.ExecState{}, "", false, err + return ib, err } runOpt := []llb.RunOption{ llb.WithCustomName(thunk.Cmdline()), // NB: this is load-bearing; it's what busts the cache with different labels - llb.Hostname(id), + llb.Hostname(thunkName), llb.AddMount("/tmp", llb.Scratch(), llb.Tmpfs()), llb.AddMount("/dev/shm", llb.Scratch(), llb.Tmpfs()), llb.AddMount(ioDir, llb.Scratch().File( @@ -762,19 +797,19 @@ func (b *buildkitBuilder) llb(ctx context.Context, thunk bass.Thunk, extraOpts . } if thunk.TLS != nil { - crt, key, err := basstls.Generate(b.runtime.Config.CertsDir, id) + crt, key, err := basstls.Generate(b.runtime.Config.CertsDir, thunkName) if err != nil { - return llb.ExecState{}, "", false, fmt.Errorf("tls: generate: %w", err) + return ib, fmt.Errorf("tls: generate: %w", err) } crtContent, err := crt.Export() if err != nil { - return llb.ExecState{}, "", false, fmt.Errorf("export crt: %w", err) + return ib, fmt.Errorf("export crt: %w", err) } keyContent, err := key.ExportPrivate() if err != nil { - return llb.ExecState{}, "", false, fmt.Errorf("export key: %w", err) + return ib, fmt.Errorf("export key: %w", err) } runOpt = append(runOpt, @@ -808,10 +843,10 @@ func (b *buildkitBuilder) llb(ctx context.Context, thunk bass.Thunk, extraOpts . } if thunk.Insecure { - needsInsecure = true + ib.needsInsecure = true runOpt = append(runOpt, - llb.WithCgroupParent(id), + llb.WithCgroupParent(thunkName), llb.Security(llb.SecurityModeInsecure)) } @@ -826,28 +861,28 @@ func (b *buildkitBuilder) llb(ctx context.Context, thunk bass.Thunk, extraOpts . mountOpt, sp, ni, err := b.initializeMount(ctx, mount.Source, targetPath) if err != nil { - return llb.ExecState{}, "", false, err + return ib, err } if targetPath == workDir { remountedWorkdir = true - sourcePath = sp + ib.sourcePath = sp } if ni { - needsInsecure = true + ib.needsInsecure = true } runOpt = append(runOpt, mountOpt) } if !remountedWorkdir { - if sourcePath != "" { + if ib.sourcePath != "" { // NB: could just call SourcePath with "", but this is to ensure there's // code coverage - runOpt = append(runOpt, llb.AddMount(workDir, runState, llb.SourcePath(sourcePath))) + runOpt = append(runOpt, llb.AddMount(workDir, ib.output, llb.SourcePath(ib.sourcePath))) } else { - runOpt = append(runOpt, llb.AddMount(workDir, runState)) + runOpt = append(runOpt, llb.AddMount(workDir, ib.output)) } } @@ -857,7 +892,21 @@ func (b *buildkitBuilder) llb(ctx context.Context, thunk bass.Thunk, extraOpts . runOpt = append(runOpt, extraOpts...) - return imageRef.Run(runOpt...), sourcePath, needsInsecure, nil + execSt := ib.fs.Run(runOpt...) + ib.output = transform(execSt, ib.sourcePath) + ib.fs = execSt.State + + // propagate thunk's entrypoint to the child + if thunk.Entrypoint != nil { // note: nil vs. [] distinction + ib.config.Entrypoint = thunk.Entrypoint + } + + // propagate thunk's default command + if thunk.DefaultArgs != nil { // note: nil vs. [] distinction + ib.config.Cmd = thunk.DefaultArgs + } + + return ib, nil } func (runtime *Buildkit) shim() (llb.State, error) { @@ -900,38 +949,91 @@ func (r *Buildkit) ref(ctx context.Context, imageRef bass.ImageRef) (string, err return imageRef.Ref() } -func (b *buildkitBuilder) image(ctx context.Context, image *bass.ThunkImage) (llb.State, llb.State, string, bool, error) { - if image == nil { - // TODO: test - return llb.Scratch(), llb.Scratch(), "", false, nil - } +type intermediateBuild struct { + fs llb.State + + output llb.State - if image.Ref != nil { + sourcePath string + needsInsecure bool + + config ocispecs.ImageConfig +} + +func (b *buildkitBuilder) image(ctx context.Context, image *bass.ThunkImage) (ib intermediateBuild, err error) { + switch { + case image == nil: + // TODO: test; how is this possible? + ib.fs = llb.Scratch() + ib.output = llb.Scratch() + return ib, nil + + case image.Ref != nil: ref, err := b.runtime.ref(ctx, *image.Ref) if err != nil { - return llb.State{}, llb.State{}, "", false, err + return ib, err } - return llb.Image( - ref, - llb.WithMetaResolver(b.resolver), - llb.Platform(b.runtime.Platform), - ), llb.Scratch(), "", false, nil - } + r, err := reference.ParseNormalizedNamed(ref) + if err == nil { + r = reference.TagNameOnly(r) + ref = r.String() + } - if image.Thunk != nil { - execState, sourcePath, needsInsecure, err := b.llb(ctx, *image.Thunk) + dgst, config, err := b.resolver.ResolveImageConfig(ctx, ref, llb.ResolveImageConfigOpt{ + ResolverType: llb.ResolverTypeRegistry, + Platform: &b.runtime.Platform, + ResolveMode: llb.ResolveModeDefault.String(), + }) if err != nil { - return llb.State{}, llb.State{}, "", false, fmt.Errorf("image thunk llb: %w", err) + return ib, err } - return execState.State, execState.GetMount(workDir), sourcePath, needsInsecure, nil - } + if dgst != "" { + r, err = reference.WithDigest(r, dgst) + if err != nil { + return ib, err + } + ref = r.String() + } - if image.Archive != nil { + st := llb.Image(ref, llb.Platform(b.runtime.Platform)) + + var img ocispecs.Image + if err := json.Unmarshal(config, &img); err != nil { + return ib, err + } + for _, env := range img.Config.Env { + parts := strings.SplitN(env, "=", 2) + if len(parts[0]) > 0 { + var v string + if len(parts) > 1 { + v = parts[1] + } + st = st.AddEnv(parts[0], v) + } + } + st = st.Dir(img.Config.WorkingDir) + if img.Architecture != "" && img.OS != "" { + st = st.Platform(ocispecs.Platform{ + OS: img.OS, + Architecture: img.Architecture, + Variant: img.Variant, + }) + } + + ib.fs = st + ib.output = llb.Scratch() + ib.config = img.Config + return ib, nil + + case image.Thunk != nil: + return b.llb(ctx, *image.Thunk, getWorkdir) + + case image.Archive != nil: file, err := image.Archive.File.Open(ctx) if err != nil { - return llb.State{}, llb.State{}, "", false, fmt.Errorf("image archive file: %w", err) + return ib, fmt.Errorf("image archive file: %w", err) } defer file.Close() @@ -940,7 +1042,7 @@ func (b *buildkitBuilder) image(ctx context.Context, image *bass.ThunkImage) (ll desc, err := stream.Import(ctx, b.runtime.ociStore) if err != nil { - return llb.State{}, llb.State{}, "", false, fmt.Errorf("image archive import: %w", err) + return ib, fmt.Errorf("image archive import: %w", err) } // NB: the repository portion of this ref doesn't actually matter, but it's @@ -949,13 +1051,13 @@ func (b *buildkitBuilder) image(ctx context.Context, image *bass.ThunkImage) (ll indexBlob, err := content.ReadBlob(ctx, b.runtime.ociStore, desc) if err != nil { - return llb.State{}, llb.State{}, "", false, fmt.Errorf("image archive read blob: %w", err) + return ib, fmt.Errorf("image archive read blob: %w", err) } var idx ocispecs.Index err = json.Unmarshal(indexBlob, &idx) if err != nil { - return llb.State{}, llb.State{}, "", false, fmt.Errorf("image archive unmarshal index: %w", err) + return ib, fmt.Errorf("image archive unmarshal index: %w", err) } platform := platforms.Only(b.runtime.Platform) @@ -988,29 +1090,31 @@ func (b *buildkitBuilder) image(ctx context.Context, image *bass.ThunkImage) (ll manifestBlob, err := content.ReadBlob(ctx, b.runtime.ociStore, m) if err != nil { - return llb.State{}, llb.State{}, "", false, fmt.Errorf("image archive read blob: %w", err) + return ib, fmt.Errorf("image archive read blob: %w", err) } var man ocispecs.Manifest err = json.Unmarshal(manifestBlob, &man) if err != nil { - return llb.State{}, llb.State{}, "", false, fmt.Errorf("image archive unmarshal manifest: %w", err) + return ib, fmt.Errorf("image archive unmarshal manifest: %w", err) } configBlob, err := content.ReadBlob(ctx, b.runtime.ociStore, man.Config) if err != nil { - return llb.State{}, llb.State{}, "", false, fmt.Errorf("image archive read blob: %w", err) + return ib, fmt.Errorf("image archive read blob: %w", err) } st, err = st.WithImageConfig(configBlob) if err != nil { - return llb.State{}, llb.State{}, "", false, fmt.Errorf("image archive with image config: %w", err) + return ib, fmt.Errorf("image archive with image config: %w", err) } - return st, llb.Scratch(), "", false, nil + ib.fs = st + ib.output = llb.Scratch() + return ib, nil } - return llb.State{}, llb.State{}, "", false, fmt.Errorf("image archive had no matching manifest for platform %s and tag %s", platforms.Format(b.runtime.Platform), tag) + return ib, fmt.Errorf("image archive had no matching manifest for platform %s and tag %s", platforms.Format(b.runtime.Platform), tag) } if image.DockerBuild != nil { @@ -1022,7 +1126,7 @@ func (b *buildkitBuilder) image(ctx context.Context, image *bass.ThunkImage) (ll ctxSt, sourcePath, needsInsecure, err := b.buildInput(ctx, contextDir) if err != nil { - return llb.State{}, llb.State{}, "", false, fmt.Errorf("image docker build input: %w", err) + return ib, fmt.Errorf("image docker build input: %w", err) } opts := map[string]string{ @@ -1053,13 +1157,13 @@ func (b *buildkitBuilder) image(ctx context.Context, image *bass.ThunkImage) (ll return nil }) if err != nil { - return llb.State{}, llb.State{}, "", false, fmt.Errorf("docker build args: %w", err) + return ib, fmt.Errorf("docker build args: %w", err) } } ctxDef, err := ctxSt.Marshal(ctx) // TODO: platform? if err != nil { - return llb.State{}, llb.State{}, "", false, fmt.Errorf("docker build marshal: %w", err) + return ib, fmt.Errorf("docker build marshal: %w", err) } var allowed []entitlements.Entitlement @@ -1120,18 +1224,22 @@ func (b *buildkitBuilder) image(ctx context.Context, image *bass.ThunkImage) (ll LocalDirs: b.localDirs, }, buildkitProduct, doBuild, statusProxy.Writer()) if err != nil { - return llb.State{}, llb.State{}, "", false, statusProxy.NiceError("build failed", err) + return ib, statusProxy.NiceError("build failed", err) } wd, err := st.GetDir(ctx) if err != nil { - return llb.State{}, llb.State{}, "", false, fmt.Errorf("get dir: %w", err) + return ib, fmt.Errorf("get dir: %w", err) } - return st, st, wd, false, nil + ib.fs = st + ib.output = st + ib.sourcePath = wd + ib.needsInsecure = needsInsecure + return ib, nil } - return llb.State{}, llb.State{}, "", false, fmt.Errorf("unsupported image type: %s", image.ToValue()) + return ib, fmt.Errorf("unsupported image type: %s", image.ToValue()) } func (b *buildkitBuilder) buildInput(ctx context.Context, input bass.ImageBuildInput) (llb.State, string, bool, error) { @@ -1202,14 +1310,15 @@ func (b *buildkitBuilder) initializeMount(ctx context.Context, source bass.Thunk } func (b *buildkitBuilder) thunkPathSt(ctx context.Context, source bass.ThunkPath) (llb.State, string, bool, error) { - thunkSt, baseSourcePath, ni, err := b.llb(ctx, source.Thunk) + ib, err := b.llb(ctx, source.Thunk, getWorkdir) if err != nil { return llb.State{}, "", false, fmt.Errorf("thunk llb: %w", err) } - st := thunkSt.GetMount(workDir) - sourcePath := filepath.Join(baseSourcePath, source.Path.FilesystemPath().FromSlash()) - return st, sourcePath, ni, nil + return ib.output, + filepath.Join(ib.sourcePath, source.Path.FilesystemPath().FromSlash()), + ib.needsInsecure, + nil } func (b *buildkitBuilder) hostPathSt(ctx context.Context, source bass.HostPath) (llb.State, string, error) { @@ -1386,3 +1495,7 @@ func (proxy *statusProxy) Wait() { func (proxy *statusProxy) NiceError(msg string, err error) bass.NiceError { return proxy.prog.WrapError(msg, err) } + +func getWorkdir(st llb.ExecState, _ string) llb.State { + return st.GetMount(workDir) +} diff --git a/pkg/runtimes/command.go b/pkg/runtimes/command.go index bb4e0d7e..24af5eae 100644 --- a/pkg/runtimes/command.go +++ b/pkg/runtimes/command.go @@ -70,8 +70,6 @@ func NewCommand(ctx context.Context, starter Starter, thunk bass.Thunk) (Command starter: starter, } - var err error - if thunk.Dir != nil { var cwd string err := cmd.resolveValue(ctx, thunk.Dir.ToValue(), &cwd) @@ -82,21 +80,10 @@ func NewCommand(ctx context.Context, starter Starter, thunk bass.Thunk) (Command cmd.Dir = &cwd } - var path string - err = cmd.resolveValue(ctx, thunk.Cmd.ToValue(), &path) + var err error + cmd.Args, err = cmd.resolveArgs(ctx, thunk.Args) if err != nil { - return Command{}, fmt.Errorf("resolve path: %w", err) - } - - cmd.Args = []string{path} - - if thunk.Args != nil { - vals, err := cmd.resolveArgs(ctx, thunk.Args) - if err != nil { - return Command{}, fmt.Errorf("resolve args: %w", err) - } - - cmd.Args = append(cmd.Args, vals...) + return Command{}, fmt.Errorf("resolve args: %w", err) } if thunk.Env != nil { diff --git a/pkg/runtimes/command_test.go b/pkg/runtimes/command_test.go index d95b4f59..929d2732 100644 --- a/pkg/runtimes/command_test.go +++ b/pkg/runtimes/command_test.go @@ -9,9 +9,11 @@ import ( "github.com/vito/is" ) +var scratch = bass.Thunk{} + var thunk = bass.Thunk{ - Cmd: bass.ThunkCmd{ - File: &bass.FilePath{Path: "yo"}, + Args: []bass.Value{ + bass.FilePath{Path: "yo"}, }, } @@ -33,8 +35,8 @@ var thunkDir = bass.ThunkPath{ var thunkName string var svcThunk = bass.Thunk{ - Cmd: bass.ThunkCmd{ - File: &bass.FilePath{Path: "yo"}, + Args: []bass.Value{ + bass.FilePath{Path: "yo"}, }, Ports: []bass.ThunkPort{ { @@ -81,8 +83,8 @@ func TestNewCommand(t *testing.T) { is := is.New(t) thunk := bass.Thunk{ - Cmd: bass.ThunkCmd{ - Cmd: &bass.CommandPath{Command: "run"}, + Args: []bass.Value{ + bass.CommandPath{Command: "run"}, }, } @@ -103,9 +105,7 @@ func TestNewCommand(t *testing.T) { t.Run("file run path", func(t *testing.T) { fileCmdThunk := thunk - fileCmdThunk.Cmd = bass.ThunkCmd{ - File: &bass.FilePath{Path: "run"}, - } + fileCmdThunk.Args = []bass.Value{bass.FilePath{Path: "run"}} is := is.New(t) cmd, err := runtimes.NewCommand(ctx, starter, fileCmdThunk) @@ -117,9 +117,7 @@ func TestNewCommand(t *testing.T) { t.Run("using a thunk file as a command", func(t *testing.T) { thunkFileCmdThunk := thunk - thunkFileCmdThunk.Cmd = bass.ThunkCmd{ - Thunk: &thunkFile, - } + thunkFileCmdThunk.Args = []bass.Value{thunkFile} is := is.New(t) cmd, err := runtimes.NewCommand(ctx, starter, thunkFileCmdThunk) @@ -142,9 +140,7 @@ func TestNewCommand(t *testing.T) { hash := cache.Hash() thunk := thunk - thunk.Cmd = bass.ThunkCmd{ - Cache: &cache, - } + thunk.Args = []bass.Value{cache} is := is.New(t) cmd, err := runtimes.NewCommand(ctx, starter, thunk) @@ -164,7 +160,7 @@ func TestNewCommand(t *testing.T) { t.Run("paths in args", func(t *testing.T) { argsThunk := thunk - argsThunk.Args = []bass.Value{thunkFile, bass.DirPath{Path: "data"}} + argsThunk.Args = append(argsThunk.Args, thunkFile, bass.DirPath{Path: "data"}) is := is.New(t) cmd, err := runtimes.NewCommand(ctx, starter, argsThunk) @@ -258,6 +254,7 @@ func TestNewCommand(t *testing.T) { t.Run("concatenating", func(t *testing.T) { concatThunk := thunk concatThunk.Args = []bass.Value{ + bass.CommandPath{Command: "run"}, bass.NewList( bass.String("--dir="), bass.DirPath{Path: "some/dir"}, @@ -306,10 +303,7 @@ func TestNewCommand(t *testing.T) { t.Run("does not mount same path twice", func(t *testing.T) { dupeMountThunk := thunk - dupeMountThunk.Cmd = bass.ThunkCmd{ - Thunk: &thunkFile, - } - dupeMountThunk.Args = []bass.Value{thunkDir} + dupeMountThunk.Args = []bass.Value{thunkFile, thunkDir} dupeMountThunk.Stdin = []bass.Value{thunkFile} dupeMountThunk.Env = bass.Bindings{"INPUT": thunkFile}.Scope() dupeMountThunk.Dir = &bass.ThunkDir{ @@ -372,7 +366,10 @@ func TestNewCommand(t *testing.T) { t.Run("addrs in args", func(t *testing.T) { argsThunk := thunk - argsThunk.Args = []bass.Value{thunkAddr} + argsThunk.Args = []bass.Value{ + bass.CommandPath{Command: "run"}, + thunkAddr, + } starter := &FakeStarter{ StartResult: runtimes.StartResult{ @@ -462,8 +459,8 @@ func TestNewCommandInDir(t *testing.T) { is := is.New(t) thunk := bass.Thunk{ - Cmd: bass.ThunkCmd{ - Cmd: &bass.CommandPath{Command: "run"}, + Args: []bass.Value{ + bass.CommandPath{Command: "run"}, }, Dir: &bass.ThunkDir{ ThunkDir: &thunkDir, diff --git a/pkg/runtimes/suite.go b/pkg/runtimes/suite.go index de348195..be7001c2 100644 --- a/pkg/runtimes/suite.go +++ b/pkg/runtimes/suite.go @@ -298,6 +298,19 @@ func Suite(t *testing.T, config bass.RuntimeConfig) { bass.String("hello from Dockerfile with env bar\nbar\n"), ), }, + { + File: "entrypoints.bass", + Result: bass.Bindings{ + "from-image": bass.String("git version 2.36.3\n"), + "from-thunk": bass.String( + "setting entrypoint\n" + + "using entrypoint\n" + + "using entrypoint again\n" + + "removing entrypoint\n" + + "no more entrypoint\n", + ), + }.Scope(), + }, } { test := test t.Run(filepath.Base(test.File), func(t *testing.T) { diff --git a/pkg/runtimes/testdata/bass.lock b/pkg/runtimes/testdata/bass.lock deleted file mode 100644 index d32ef3cd..00000000 --- a/pkg/runtimes/testdata/bass.lock +++ /dev/null @@ -1,264 +0,0 @@ -memos: { - module: { - cmd: { - command: { - name: "run" - } - } - } - calls: { - binding: "resolve" - results: { - input: { - array: { - values: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - } - } - } - } - output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine" - } - } - } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1243f395ee852a8d9730fc2ad" - } - } - } - } - } - } - results: { - input: { - array: { - values: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "registry" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - } - } - } - } - output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "registry" - } - } - } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:83bb78d7b28f1ac99c68133af32c93e9a1c149bcd3cb6e683a3ee56e312f1c96" - } - } - } - } - } - } - results: { - input: { - array: { - values: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "busybox" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - } - } - } - } - output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "busybox" - } - } - } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:20142e89dab967c01765b0aea3be4cec3a5957cc330f061e5503ef6168ae6613" - } - } - } - } - } - } - } -} diff --git a/pkg/runtimes/testdata/entrypoints.bass b/pkg/runtimes/testdata/entrypoints.bass new file mode 100644 index 00000000..bd4c2dc1 --- /dev/null +++ b/pkg/runtimes/testdata/entrypoints.bass @@ -0,0 +1,26 @@ +{:from-image + (-> (from (linux/alpine/git :2.36.3) + ($ --version)) + (read :raw) + next) + :from-thunk + (-> (from (linux/alpine) + ; set an entrypoint + ; NB: there's currently no way to just override an entrypoint on an image... + (-> ($ sh -c "echo setting entrypoint >> out") + (with-entrypoint ["sh"])) + + ; use entrypoint + ($ -c "echo using entrypoint >> out") + ($ -c "echo using entrypoint again >> out") + + ; erase entrypoint + (-> ($ -c "echo removing entrypoint >> out") + (with-entrypoint [])) + + ; use no entryopint + ($ sh -c "echo no more entrypoint >> out")) + (subpath ./out) + (read :raw) + next) + } diff --git a/proto/bass.proto b/proto/bass.proto index 1c55e076..1012f1d5 100644 --- a/proto/bass.proto +++ b/proto/bass.proto @@ -20,13 +20,13 @@ message Value { ThunkPath thunk_path = 13; LogicalPath logical_path = 14; ThunkAddr thunk_addr = 15; + CachePath cache_path = 16; }; }; message Thunk { ThunkImage image = 1; bool insecure = 2; - ThunkCmd cmd = 3; repeated Value args = 4; repeated Value stdin = 5; repeated Binding env = 6; @@ -105,17 +105,6 @@ message Platform { string arch = 2; }; -message ThunkCmd { - oneof cmd { - CommandPath command = 1; - FilePath file = 2; - ThunkPath thunk = 3; - HostPath host = 4; - LogicalPath logical = 5; - CachePath cache = 6; - }; -}; - message ThunkDir { oneof dir { DirPath local = 12; diff --git a/std/root.bass b/std/root.bass index 537ce2bf..39fc3452 100644 --- a/std/root.bass +++ b/std/root.bass @@ -283,7 +283,8 @@ [] [] [thunk-form & rest-forms] (let [thunk (eval thunk-form scope) - modname (string->symbol (path-stem (thunk-cmd thunk)))] + cmd (first (thunk-args thunk)) + modname (string->symbol (path-stem cmd))] (cons (eval [def modname [load thunk]] scope) (bind-modules rest-forms scope))))) diff --git a/std/run.bass b/std/run.bass index c16da2e5..8c230463 100644 --- a/std/run.bass +++ b/std/run.bass @@ -33,10 +33,8 @@ ; with $ are resolved to their binding with the leading $ removed. ; ; => ($ sh -c "echo Hello, world!") - (defop $ [cmd & args] scope - (let [c (resolve-cmd cmd scope) - as (resolve-args args scope)] - (with-args (c) as)))) + (defop $ args scope + (with-args scratch (resolve-args args scope)))) ; chain a sequence of thunks starting from an initial image ; @@ -65,11 +63,9 @@ ; the original cmd + args. ; ; => (wrap-cmd ($ go test "./...") .strace "-f") -(defn wrap-cmd [thunk cmd & args] +(defn wrap-cmd [thunk & args] (-> thunk - (with-cmd cmd) - (with-args (concat args (cons (thunk-cmd thunk) - (thunk-args thunk)))))) + (with-args (concat args (thunk-args thunk))))) (provide [linux] (defn memo-resolve [memos] From ee087a4ac11e4b8431fffd5e8b7b37b5ff8f7d88 Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Mon, 3 Apr 2023 00:40:11 -0400 Subject: [PATCH 02/16] render thunks with more {{noise}} <> are too subtle, {{foo}}/bar is much easier to read than /bar --- pkg/bass/thunk.go | 6 +++--- pkg/bass/value_test.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/bass/thunk.go b/pkg/bass/thunk.go index 78e551fc..c754259f 100644 --- a/pkg/bass/thunk.go +++ b/pkg/bass/thunk.go @@ -231,7 +231,7 @@ func (thunk Thunk) RunState(stdout io.Writer) RunState { func (thunk Thunk) RunDir() Path { if len(thunk.Args) == 0 { - panic(fmt.Sprintf("Thunk.RunDir: no arguments: %+v", thunk)) + panic(fmt.Sprintf("no arguments: %+v", thunk)) } cmd := thunk.Args[0] @@ -255,7 +255,7 @@ func (thunk Thunk) RunDir() Path { } else if cmd.Decode(&cachep) == nil { return cachep.Dir() } else { - panic(fmt.Sprintf("ThunkCmd.RunDir: no value present: %+v", cmd)) + panic(fmt.Sprintf("cannot infer run dir from command %s: %s", cmd, thunk)) } } @@ -518,7 +518,7 @@ func (thunk Thunk) WithTLS(cert, key FilePath) Thunk { var _ Value = Thunk{} func (thunk Thunk) String() string { - return fmt.Sprintf("", thunk.Name(), NewList(thunk.Args...)) + return fmt.Sprintf("{{thunk %s: %s}}", thunk.Name(), thunk.Cmdline()) } func (thunk Thunk) Equal(other Value) bool { diff --git a/pkg/bass/value_test.go b/pkg/bass/value_test.go index 72f04f2e..5218842a 100644 --- a/pkg/bass/value_test.go +++ b/pkg/bass/value_test.go @@ -470,7 +470,7 @@ func TestString(t *testing.T) { Dir: &bass.DirPath{"dir"}, }, }, - "/dir/", + "{{thunk CBA5NVSCDITAM: ./file}}/dir/", }, } { t.Run(fmt.Sprintf("%T", test.src), func(t *testing.T) { From 7a11f957ed319bfc98a97be39b6ac0f00b775c33 Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Mon, 3 Apr 2023 00:43:38 -0400 Subject: [PATCH 03/16] support un-setting entrypoints, fix breakages --- bass/bass.bass | 22 +++++-------------- demos/booklit/test-last-10.bass | 2 +- demos/readme-prep.bass | 2 +- docs/lit/guide.lit | 2 +- docs/lit/index.lit | 9 ++++---- pkg/runtimes/buildkit.go | 29 ++++++++++++++++---------- pkg/runtimes/suite.go | 3 ++- pkg/runtimes/testdata/entrypoints.bass | 6 ++++++ std/git.bass | 4 +++- 9 files changed, 42 insertions(+), 37 deletions(-) diff --git a/bass/bass.bass b/bass/bass.bass index 292c651f..77d1f195 100644 --- a/bass/bass.bass +++ b/bass/bass.bass @@ -10,7 +10,7 @@ (defn checkout [sha] (git:github/vito/bass/sha/ sha)) -(provide [subgit] +(provide [subgit git-submodules] ; produces a fresh checkout of the last commit that affected the given paths (defn subgit [src & paths] (git:checkout (remote src) (latest-commit src paths))) @@ -24,26 +24,14 @@ trim)) (defn remote [src] - (git-out src ($ git remote get-url origin))) + (git-out src ($ remote get-url origin))) (defn latest-commit [src paths] - (git-out src ($ git log -n1 "--pretty=format:%H" -- & $paths)))) - -(provide [git-submodules] - ; TODO: remove once this ships and bass-loop is upgraded - ; - ; reads all values from the source into a list - ; - ; => (take-all (list->source [1 2 3])) - (defn take-all [source] - (let [val (next source _)] - (if (ignore? val) - [] - (cons val (take-all source))))) + (git-out src ($ log -n1 "--pretty=format:%H" -- & $paths))) (defn git-submodules [src] (map (fn [[_ path]] (string->dir path)) - (-> ($ git config --file src/.gitmodules --get-regexp path) + (-> ($ config --file src/.gitmodules --get-regexp path) (with-image (linux/alpine/git)) (read :unix-table) take-all)))) @@ -152,7 +140,7 @@ smoke-tests)) (def test-depot - (-> ($ certstrap init --cn bass --passphrase "") + (-> ($ init --cn bass --passphrase "") (with-image (linux/squareup/certstrap)) (subpath ./out/))) diff --git a/demos/booklit/test-last-10.bass b/demos/booklit/test-last-10.bass index 8bfdb514..43dc23be 100755 --- a/demos/booklit/test-last-10.bass +++ b/demos/booklit/test-last-10.bass @@ -7,7 +7,7 @@ booklit (load (latest/bass/booklit.bass)) commits (from (linux/alpine/git) (cd latest - ($ git rev-list "HEAD~10..HEAD")))] + ($ rev-list "HEAD~10..HEAD")))] (for [sha (read commits :lines)] (let [src (git:github/vito/booklit/sha/ (string->dir sha)) ok? (succeeds? (booklit:tests src testflags))] diff --git a/demos/readme-prep.bass b/demos/readme-prep.bass index 47df85a5..2943a6c7 100644 --- a/demos/readme-prep.bass +++ b/demos/readme-prep.bass @@ -1,7 +1,7 @@ ; prefetch images used by readme demo so it's not too long (run (from (linux/alpine/git) - ($ git --version))) + ($ --version))) (run (from (linux/golang) ($ go version))) diff --git a/docs/lit/guide.lit b/docs/lit/guide.lit index 2cfacec3..4c845b66 100644 --- a/docs/lit/guide.lit +++ b/docs/lit/guide.lit @@ -253,7 +253,7 @@ for common tasks. If you'd like to learn the language, see \reference{bassics}. (def cloned (from (linux/alpine/git) - ($ git clone "https://github.com/vito/bass" ./repo/))) + ($ clone "https://github.com/vito/bass" ./repo/))) (go-build cloned/repo/ "./cmd/...") }}}{ diff --git a/docs/lit/index.lit b/docs/lit/index.lit index 363b1ccc..be18afc2 100644 --- a/docs/lit/index.lit +++ b/docs/lit/index.lit @@ -68,7 +68,7 @@ release}{https://github.com/vito/bass/releases/latest} and skim the }{{{ ; BAD (from (linux/alpine/git) - ($ git clone "https://github.com/vito/bass" ./)) + ($ clone "https://github.com/vito/bass" ./)) }}}{ If you run this thunk somewhere else it might return something different. It'll also be cached forever, so you'll never get new commits. @@ -193,10 +193,11 @@ release}{https://github.com/vito/bass/releases/latest} and skim the The \b{linux} path root resolves an image reference to a digest and memoizes its result into \code{*memos*} if defined. }{{{ - (use (.git (linux/alpine/git))) ; saves digest into *memos* + (run (from (linux/alpine) ; resolves linux/alpine and writes to *memos* + ($ echo hi))) - (run (from (linux/alpine/git) ; uses the digest from *memos* - ($ cat $*memos*))) ; reveal the wizard behind the curtain + (run (from (linux/alpine) ; uses the digest from *memos* + ($ cat $*memos*))) ; reveals the wizard behind the curtain }}}{ The \b{git-github} path root resolves a branch or tag reference to a commit and returns its \b{git-checkout}, memoizing the commit in \code{*memos*} if diff --git a/pkg/runtimes/buildkit.go b/pkg/runtimes/buildkit.go index a9a5e937..b17865d8 100644 --- a/pkg/runtimes/buildkit.go +++ b/pkg/runtimes/buildkit.go @@ -760,7 +760,24 @@ func (b *buildkitBuilder) llb( return ib, err } - cmd.Args = append(ib.config.Entrypoint, cmd.Args...) + entrypoint := ib.config.Entrypoint + + // propagate thunk's entrypoint to the child + if thunk.Entrypoint != nil { // note: nil vs. [] distinction + ib.config.Entrypoint = thunk.Entrypoint + } + + // propagate thunk's default command + if thunk.DefaultArgs != nil { // note: nil vs. [] distinction + ib.config.Cmd = thunk.DefaultArgs + } + + if cmd.Args == nil { // note: nil vs. [] distinction + // no command; we're just overriding config + return ib, nil + } + + cmd.Args = append(entrypoint, cmd.Args...) cmdPayload, err := bass.MarshalJSON(cmd) if err != nil { @@ -896,16 +913,6 @@ func (b *buildkitBuilder) llb( ib.output = transform(execSt, ib.sourcePath) ib.fs = execSt.State - // propagate thunk's entrypoint to the child - if thunk.Entrypoint != nil { // note: nil vs. [] distinction - ib.config.Entrypoint = thunk.Entrypoint - } - - // propagate thunk's default command - if thunk.DefaultArgs != nil { // note: nil vs. [] distinction - ib.config.Cmd = thunk.DefaultArgs - } - return ib, nil } diff --git a/pkg/runtimes/suite.go b/pkg/runtimes/suite.go index be7001c2..113fa4f0 100644 --- a/pkg/runtimes/suite.go +++ b/pkg/runtimes/suite.go @@ -301,7 +301,8 @@ func Suite(t *testing.T, config bass.RuntimeConfig) { { File: "entrypoints.bass", Result: bass.Bindings{ - "from-image": bass.String("git version 2.36.3\n"), + "from-image": bass.String("git version 2.36.3\n"), + "unset-image": bass.String("git version 2.36.3\n"), "from-thunk": bass.String( "setting entrypoint\n" + "using entrypoint\n" + diff --git a/pkg/runtimes/testdata/entrypoints.bass b/pkg/runtimes/testdata/entrypoints.bass index bd4c2dc1..76c5cdc1 100644 --- a/pkg/runtimes/testdata/entrypoints.bass +++ b/pkg/runtimes/testdata/entrypoints.bass @@ -3,6 +3,12 @@ ($ --version)) (read :raw) next) + :unset-image + (-> (from (linux/alpine/git :2.36.3) + (with-entrypoint ($) []) + ($ git --version)) + (read :raw) + next) :from-thunk (-> (from (linux/alpine) ; set an entrypoint diff --git a/std/git.bass b/std/git.bass index b416f584..39538145 100644 --- a/std/git.bass +++ b/std/git.bass @@ -2,7 +2,9 @@ (def *git-image* (case (next *stdin* :none) :none (error "git image must be provided") - image image)) + image (from image + ; ignore any entrypoint, we just run regular git commands + (with-entrypoint ($) [])))) ; resolves a ref to a sha at the remote repo ; From d5d96eca42cedb2be94070c79f4d1516601aae02 Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Mon, 3 Apr 2023 00:44:27 -0400 Subject: [PATCH 04/16] Dagger: respect entrypoint and default args --- pkg/runtimes/dagger.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/pkg/runtimes/dagger.go b/pkg/runtimes/dagger.go index 1f21f849..bbcc68dd 100644 --- a/pkg/runtimes/dagger.go +++ b/pkg/runtimes/dagger.go @@ -241,7 +241,6 @@ func (runtime *Dagger) container(ctx context.Context, thunk bass.Thunk) (*dagger ctr := root. WithMountedTemp("/tmp"). WithMountedTemp("/dev/shm"). - WithEntrypoint(nil). WithWorkdir(workDir) id, err := thunk.Hash() @@ -319,10 +318,22 @@ func (runtime *Dagger) container(ctx context.Context, thunk bass.Thunk) (*dagger ctr = ctr.WithSecretVariable(env.Name, secret) } - return ctr.WithExec(cmd.Args, dagger.ContainerWithExecOpts{ + ctr = ctr.WithExec(cmd.Args, dagger.ContainerWithExecOpts{ Stdin: string(cmd.Stdin), InsecureRootCapabilities: thunk.Insecure, - }), nil + }) + + if thunk.Entrypoint != nil { + ctr = ctr.WithEntrypoint(thunk.Entrypoint) + } + + if thunk.DefaultArgs != nil { + ctr = ctr.WithDefaultArgs(dagger.ContainerWithDefaultArgsOpts{ + Args: thunk.DefaultArgs, + }) + } + + return ctr, nil } var epoch = time.Date(1985, 10, 26, 8, 15, 0, 0, time.UTC) From 1df5ca608163d4c09fef2a450bc363a394455bce Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Mon, 3 Apr 2023 00:45:13 -0400 Subject: [PATCH 05/16] add fresh bass.locks --- bass/bass.lock | 428 ++++++++++++++++++++++++++++++++ demos/bass.lock | 0 pkg/runtimes/testdata/bass.lock | 180 ++++++++++++++ 3 files changed, 608 insertions(+) create mode 100644 bass/bass.lock create mode 100644 demos/bass.lock create mode 100644 pkg/runtimes/testdata/bass.lock diff --git a/bass/bass.lock b/bass/bass.lock new file mode 100644 index 00000000..1611e3f9 --- /dev/null +++ b/bass/bass.lock @@ -0,0 +1,428 @@ +memos: { + module: { + args: { + command_path: { + name: "run" + } + } + } + calls: { + binding: "resolve" + results: { + input: { + array: { + values: { + object: { + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } + } + } + } + } + bindings: { + symbol: "repository" + value: { + string: { + value: "alpine/git" + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } + } + } + } + } + } + output: { + object: { + bindings: { + symbol: "repository" + value: { + string: { + value: "alpine/git" + } + } + } + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "architecture" + value: { + string: { + value: "amd64" + } + } + } + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } + } + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } + } + bindings: { + symbol: "digest" + value: { + string: { + value: "sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2" + } + } + } + } + } + } + results: { + input: { + array: { + values: { + object: { + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } + } + } + } + } + bindings: { + symbol: "repository" + value: { + string: { + value: "ubuntu" + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } + } + } + } + } + } + output: { + object: { + bindings: { + symbol: "repository" + value: { + string: { + value: "ubuntu" + } + } + } + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "architecture" + value: { + string: { + value: "amd64" + } + } + } + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } + } + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } + } + bindings: { + symbol: "digest" + value: { + string: { + value: "sha256:67211c14fa74f070d27cc59d69a7fa9aeff8e28ea118ef3babc295a0428a6d21" + } + } + } + } + } + } + results: { + input: { + array: { + values: { + object: { + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } + } + } + } + } + bindings: { + symbol: "repository" + value: { + string: { + value: "alpine" + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } + } + } + } + } + } + output: { + object: { + bindings: { + symbol: "repository" + value: { + string: { + value: "alpine" + } + } + } + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "architecture" + value: { + string: { + value: "amd64" + } + } + } + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } + } + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } + } + bindings: { + symbol: "digest" + value: { + string: { + value: "sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126" + } + } + } + } + } + } + results: { + input: { + array: { + values: { + object: { + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } + } + } + } + } + bindings: { + symbol: "repository" + value: { + string: { + value: "squareup/certstrap" + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } + } + } + } + } + } + output: { + object: { + bindings: { + symbol: "repository" + value: { + string: { + value: "squareup/certstrap" + } + } + } + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "architecture" + value: { + string: { + value: "amd64" + } + } + } + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } + } + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } + } + bindings: { + symbol: "digest" + value: { + string: { + value: "sha256:c18a2389cf102a78ed6b42a2ae56ab81d898de30cdf1aca79a16bec15b22f7f2" + } + } + } + } + } + } + } +} +memos: { + module: { + args: { + command_path: { + name: "git" + } + } + stdin: { + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" + } + repository: "alpine/git" + tag: "latest" + digest: "sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2" + } + } + } + } + } + calls: { + binding: "ls-remote" + results: { + input: { + array: { + values: { + string: { + value: "https://github.com/vito/tabs" + } + } + values: { + string: { + value: "main" + } + } + } + } + output: { + string: { + value: "06cbb3adb6ceb9f54e6d747cb56c8f738e893fb1" + } + } + } + } +} diff --git a/demos/bass.lock b/demos/bass.lock new file mode 100644 index 00000000..e69de29b diff --git a/pkg/runtimes/testdata/bass.lock b/pkg/runtimes/testdata/bass.lock new file mode 100644 index 00000000..fa67c2fe --- /dev/null +++ b/pkg/runtimes/testdata/bass.lock @@ -0,0 +1,180 @@ +memos: { + module: { + args: { + command_path: { + name: "run" + } + } + } + calls: { + binding: "resolve" + results: { + input: { + array: { + values: { + object: { + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } + } + } + } + } + bindings: { + symbol: "repository" + value: { + string: { + value: "alpine/git" + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "2.36.3" + } + } + } + } + } + } + } + output: { + object: { + bindings: { + symbol: "repository" + value: { + string: { + value: "alpine/git" + } + } + } + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "architecture" + value: { + string: { + value: "amd64" + } + } + } + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } + } + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "2.36.3" + } + } + } + } + } + } + results: { + input: { + array: { + values: { + object: { + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } + } + } + } + } + bindings: { + symbol: "repository" + value: { + string: { + value: "alpine" + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } + } + } + } + } + } + output: { + object: { + bindings: { + symbol: "repository" + value: { + string: { + value: "alpine" + } + } + } + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "architecture" + value: { + string: { + value: "amd64" + } + } + } + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } + } + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } + } + } + } + } + } +} From 2e15e046c658612047380dc9e7ab012264cb7bc1 Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Mon, 3 Apr 2023 01:00:58 -0400 Subject: [PATCH 06/16] Dagger: fix entrypoint removal behavior --- pkg/runtimes/dagger.go | 10 ++++++---- pkg/runtimes/suite.go | 5 +++++ pkg/runtimes/testdata/entrypoints.bass | 18 +++++++++++++++++- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/pkg/runtimes/dagger.go b/pkg/runtimes/dagger.go index bbcc68dd..6fe52ce4 100644 --- a/pkg/runtimes/dagger.go +++ b/pkg/runtimes/dagger.go @@ -318,10 +318,12 @@ func (runtime *Dagger) container(ctx context.Context, thunk bass.Thunk) (*dagger ctr = ctr.WithSecretVariable(env.Name, secret) } - ctr = ctr.WithExec(cmd.Args, dagger.ContainerWithExecOpts{ - Stdin: string(cmd.Stdin), - InsecureRootCapabilities: thunk.Insecure, - }) + if cmd.Args != nil { + ctr = ctr.WithExec(cmd.Args, dagger.ContainerWithExecOpts{ + Stdin: string(cmd.Stdin), + InsecureRootCapabilities: thunk.Insecure, + }) + } if thunk.Entrypoint != nil { ctr = ctr.WithEntrypoint(thunk.Entrypoint) diff --git a/pkg/runtimes/suite.go b/pkg/runtimes/suite.go index 113fa4f0..43164903 100644 --- a/pkg/runtimes/suite.go +++ b/pkg/runtimes/suite.go @@ -310,6 +310,11 @@ func Suite(t *testing.T, config bass.RuntimeConfig) { "removing entrypoint\n" + "no more entrypoint\n", ), + "from-thunk-scratch": bass.String( + "using entrypoint\n" + + "using entrypoint again\n" + + "no more entrypoint\n", + ), }.Scope(), }, } { diff --git a/pkg/runtimes/testdata/entrypoints.bass b/pkg/runtimes/testdata/entrypoints.bass index 76c5cdc1..6cc5cfda 100644 --- a/pkg/runtimes/testdata/entrypoints.bass +++ b/pkg/runtimes/testdata/entrypoints.bass @@ -12,7 +12,6 @@ :from-thunk (-> (from (linux/alpine) ; set an entrypoint - ; NB: there's currently no way to just override an entrypoint on an image... (-> ($ sh -c "echo setting entrypoint >> out") (with-entrypoint ["sh"])) @@ -29,4 +28,21 @@ (subpath ./out) (read :raw) next) + :from-thunk-scratch + (-> (from (linux/alpine) + ; set an entrypoint + (with-entrypoint ($) ["sh"]) + + ; use entrypoint + ($ -c "echo using entrypoint >> out") + ($ -c "echo using entrypoint again >> out") + + ; erase entrypoint + (with-entrypoint ($) []) + + ; use no entryopint + ($ sh -c "echo no more entrypoint >> out")) + (subpath ./out) + (read :raw) + next) } From e7690487923c6211596251e7116535b93bd20fe7 Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Mon, 3 Apr 2023 03:18:24 -0400 Subject: [PATCH 07/16] set labels on config --- pkg/runtimes/buildkit.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pkg/runtimes/buildkit.go b/pkg/runtimes/buildkit.go index b17865d8..7efc2eba 100644 --- a/pkg/runtimes/buildkit.go +++ b/pkg/runtimes/buildkit.go @@ -772,6 +772,22 @@ func (b *buildkitBuilder) llb( ib.config.Cmd = thunk.DefaultArgs } + if thunk.Labels != nil { + ib.config.Labels = map[string]string{} + err := thunk.Labels.Each(func(k bass.Symbol, v bass.Value) error { + var str string + if err := v.Decode(&str); err != nil { + return err + } + + ib.config.Labels[k.String()] = str + return nil + }) + if err != nil { + return ib, fmt.Errorf("labels: %w", err) + } + } + if cmd.Args == nil { // note: nil vs. [] distinction // no command; we're just overriding config return ib, nil From e10fbc1ac1da07feb710011fe668d629091c3ecc Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Fri, 7 Apr 2023 18:57:29 -0400 Subject: [PATCH 08/16] don't respect entrypoint after all Feels confusing in Bass thunk syntax. Dockerfiles don't respect them either. (from (linux/alpine/git) ($ clone)) (from (linux/alpine/git) ($ git clone)) ; much more recognizeable! I could see Bass respecting them if/when it supports directly running an image like (run (linux/redis)) though. --- bass/bass.bass | 8 +-- demos/booklit/test-last-10.bass | 2 +- demos/readme-prep.bass | 2 +- docs/lit/guide.lit | 2 +- docs/lit/index.lit | 2 +- pkg/bass/thunk.go | 12 ++-- pkg/runtimes/buildkit.go | 4 -- pkg/runtimes/dagger.go | 21 ++++++ pkg/runtimes/suite.go | 19 +---- pkg/runtimes/testdata/entrypoints.bass | 99 +++++++++++++------------- std/git.bass | 4 +- 11 files changed, 91 insertions(+), 84 deletions(-) diff --git a/bass/bass.bass b/bass/bass.bass index 77d1f195..c151915d 100644 --- a/bass/bass.bass +++ b/bass/bass.bass @@ -24,14 +24,14 @@ trim)) (defn remote [src] - (git-out src ($ remote get-url origin))) + (git-out src ($ git remote get-url origin))) (defn latest-commit [src paths] - (git-out src ($ log -n1 "--pretty=format:%H" -- & $paths))) + (git-out src ($ git log -n1 "--pretty=format:%H" -- & $paths))) (defn git-submodules [src] (map (fn [[_ path]] (string->dir path)) - (-> ($ config --file src/.gitmodules --get-regexp path) + (-> ($ git config --file src/.gitmodules --get-regexp path) (with-image (linux/alpine/git)) (read :unix-table) take-all)))) @@ -140,7 +140,7 @@ smoke-tests)) (def test-depot - (-> ($ init --cn bass --passphrase "") + (-> ($ certstrap init --cn bass --passphrase "") (with-image (linux/squareup/certstrap)) (subpath ./out/))) diff --git a/demos/booklit/test-last-10.bass b/demos/booklit/test-last-10.bass index 43dc23be..8bfdb514 100755 --- a/demos/booklit/test-last-10.bass +++ b/demos/booklit/test-last-10.bass @@ -7,7 +7,7 @@ booklit (load (latest/bass/booklit.bass)) commits (from (linux/alpine/git) (cd latest - ($ rev-list "HEAD~10..HEAD")))] + ($ git rev-list "HEAD~10..HEAD")))] (for [sha (read commits :lines)] (let [src (git:github/vito/booklit/sha/ (string->dir sha)) ok? (succeeds? (booklit:tests src testflags))] diff --git a/demos/readme-prep.bass b/demos/readme-prep.bass index 2943a6c7..47df85a5 100644 --- a/demos/readme-prep.bass +++ b/demos/readme-prep.bass @@ -1,7 +1,7 @@ ; prefetch images used by readme demo so it's not too long (run (from (linux/alpine/git) - ($ --version))) + ($ git --version))) (run (from (linux/golang) ($ go version))) diff --git a/docs/lit/guide.lit b/docs/lit/guide.lit index 4c845b66..2cfacec3 100644 --- a/docs/lit/guide.lit +++ b/docs/lit/guide.lit @@ -253,7 +253,7 @@ for common tasks. If you'd like to learn the language, see \reference{bassics}. (def cloned (from (linux/alpine/git) - ($ clone "https://github.com/vito/bass" ./repo/))) + ($ git clone "https://github.com/vito/bass" ./repo/))) (go-build cloned/repo/ "./cmd/...") }}}{ diff --git a/docs/lit/index.lit b/docs/lit/index.lit index be18afc2..226ef5a0 100644 --- a/docs/lit/index.lit +++ b/docs/lit/index.lit @@ -68,7 +68,7 @@ release}{https://github.com/vito/bass/releases/latest} and skim the }{{{ ; BAD (from (linux/alpine/git) - ($ clone "https://github.com/vito/bass" ./)) + ($ git clone "https://github.com/vito/bass" ./)) }}}{ If you run this thunk somewhere else it might return something different. It'll also be cached forever, so you'll never get new commits. diff --git a/pkg/bass/thunk.go b/pkg/bass/thunk.go index c754259f..d1df9ad1 100644 --- a/pkg/bass/thunk.go +++ b/pkg/bass/thunk.go @@ -78,13 +78,17 @@ type Thunk struct { TLS *ThunkTLS `json:"tls,omitempty"` // Entrypoint configures a static command and arguments that will be - // prepended to child commands. + // prepended to any command the published container runs. // - // A nil value inherits from the parent. An empty slice removes it. + // A null value inherits from the parent. An empty slice removes it. + // + // Note that Bass thunks don't actually use the entrypoint themselves. Entrypoint []string `json:"entrypoint,omitempty"` - // DefaultArgs configures a command and arguments to use if a child execution - // does not specify a command. + // DefaultArgs configures a command and arguments to used when the published + // container runs. + // + // Note that Bass thunks don't actually use the default args themselves. DefaultArgs []string `json:"default_args,omitempty"` } diff --git a/pkg/runtimes/buildkit.go b/pkg/runtimes/buildkit.go index 7efc2eba..40252d66 100644 --- a/pkg/runtimes/buildkit.go +++ b/pkg/runtimes/buildkit.go @@ -760,8 +760,6 @@ func (b *buildkitBuilder) llb( return ib, err } - entrypoint := ib.config.Entrypoint - // propagate thunk's entrypoint to the child if thunk.Entrypoint != nil { // note: nil vs. [] distinction ib.config.Entrypoint = thunk.Entrypoint @@ -793,8 +791,6 @@ func (b *buildkitBuilder) llb( return ib, nil } - cmd.Args = append(entrypoint, cmd.Args...) - cmdPayload, err := bass.MarshalJSON(cmd) if err != nil { return ib, err diff --git a/pkg/runtimes/dagger.go b/pkg/runtimes/dagger.go index 6fe52ce4..68db78d1 100644 --- a/pkg/runtimes/dagger.go +++ b/pkg/runtimes/dagger.go @@ -319,10 +319,31 @@ func (runtime *Dagger) container(ctx context.Context, thunk bass.Thunk) (*dagger } if cmd.Args != nil { + ep, err := ctr.Entrypoint(ctx) + if err != nil { + return nil, err + } + + // Don't respect the entrypoint; this is way too confusing: + // + // (from (linux/alpine/git) + // ($ clone "https://github.com/vito/bass")) + // + // Bass thunks feel are similar to Dockerfiles, which also don't respect + // entrypoints. + if len(ep) > 0 { + ctr = ctr.WithEntrypoint(nil) + } + ctr = ctr.WithExec(cmd.Args, dagger.ContainerWithExecOpts{ Stdin: string(cmd.Stdin), InsecureRootCapabilities: thunk.Insecure, }) + + // Restore the entrypoint so it's still around when publishing. + if len(ep) > 0 { + ctr = ctr.WithEntrypoint(ep) + } } if thunk.Entrypoint != nil { diff --git a/pkg/runtimes/suite.go b/pkg/runtimes/suite.go index 43164903..0e86ce25 100644 --- a/pkg/runtimes/suite.go +++ b/pkg/runtimes/suite.go @@ -299,23 +299,8 @@ func Suite(t *testing.T, config bass.RuntimeConfig) { ), }, { - File: "entrypoints.bass", - Result: bass.Bindings{ - "from-image": bass.String("git version 2.36.3\n"), - "unset-image": bass.String("git version 2.36.3\n"), - "from-thunk": bass.String( - "setting entrypoint\n" + - "using entrypoint\n" + - "using entrypoint again\n" + - "removing entrypoint\n" + - "no more entrypoint\n", - ), - "from-thunk-scratch": bass.String( - "using entrypoint\n" + - "using entrypoint again\n" + - "no more entrypoint\n", - ), - }.Scope(), + File: "entrypoints.bass", + Result: bass.Null{}, }, } { test := test diff --git a/pkg/runtimes/testdata/entrypoints.bass b/pkg/runtimes/testdata/entrypoints.bass index 6cc5cfda..03fe2d44 100644 --- a/pkg/runtimes/testdata/entrypoints.bass +++ b/pkg/runtimes/testdata/entrypoints.bass @@ -1,48 +1,51 @@ -{:from-image - (-> (from (linux/alpine/git :2.36.3) - ($ --version)) - (read :raw) - next) - :unset-image - (-> (from (linux/alpine/git :2.36.3) - (with-entrypoint ($) []) - ($ git --version)) - (read :raw) - next) - :from-thunk - (-> (from (linux/alpine) - ; set an entrypoint - (-> ($ sh -c "echo setting entrypoint >> out") - (with-entrypoint ["sh"])) - - ; use entrypoint - ($ -c "echo using entrypoint >> out") - ($ -c "echo using entrypoint again >> out") - - ; erase entrypoint - (-> ($ -c "echo removing entrypoint >> out") - (with-entrypoint [])) - - ; use no entryopint - ($ sh -c "echo no more entrypoint >> out")) - (subpath ./out) - (read :raw) - next) - :from-thunk-scratch - (-> (from (linux/alpine) - ; set an entrypoint - (with-entrypoint ($) ["sh"]) - - ; use entrypoint - ($ -c "echo using entrypoint >> out") - ($ -c "echo using entrypoint again >> out") - - ; erase entrypoint - (with-entrypoint ($) []) - - ; use no entryopint - ($ sh -c "echo no more entrypoint >> out")) - (subpath ./out) - (read :raw) - next) - } +(defn tar-file [tar path] + (defn find-file [stream] + (let [file (next stream) + info (meta file) + name (path-name file)] + (if (= name path) + file + (find-file stream)))) + + (find-file (read tar :tar))) + +(defn entrypoint [thunk] + (let [config-path (-> (tar-file (export thunk) "manifest.json") + (read :json) + next + first ; contains array of manifests + :Config + string->fs-path) + config (-> (tar-file (export thunk) (path-name config-path)) + (read :json) + next + :config)] + (:Entrypoint config null))) + +(def from-image + (from (linux/alpine/git :2.36.3) + ($ git --version))) + +(assert = "git version 2.36.3" (-> from-image (read :lines) next)) +(assert = ["git"] (entrypoint from-image)) + +(def unset-image + (from (linux/alpine/git :2.36.3) + (with-entrypoint ($) []) + ($ git --version))) + +(assert = "git version 2.36.3" + (-> unset-image (read :lines) next)) +(assert null? (entrypoint unset-image)) + +(def set-thunk + (from (linux/alpine) + (with-entrypoint ($) ["sh"]))) + +(assert = ["sh"] (entrypoint set-thunk)) + +(def keeps-entrypoint + (from set-thunk + ($ echo "Hello, world!"))) + +(assert = ["sh"] (entrypoint keeps-entrypoint)) diff --git a/std/git.bass b/std/git.bass index 39538145..b416f584 100644 --- a/std/git.bass +++ b/std/git.bass @@ -2,9 +2,7 @@ (def *git-image* (case (next *stdin* :none) :none (error "git image must be provided") - image (from image - ; ignore any entrypoint, we just run regular git commands - (with-entrypoint ($) [])))) + image image)) ; resolves a ref to a sha at the remote repo ; From 2b73c4cf51dae762e47ab5f5c86a29033a4bac97 Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Sat, 8 Apr 2023 10:46:03 -0400 Subject: [PATCH 09/16] test the grpc runtime client/server --- pkg/runtimes/grpc.go | 30 ++++++++++++++++ pkg/runtimes/grpc_test.go | 76 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 pkg/runtimes/grpc_test.go diff --git a/pkg/runtimes/grpc.go b/pkg/runtimes/grpc.go index 8c16fa76..3b4c1232 100644 --- a/pkg/runtimes/grpc.go +++ b/pkg/runtimes/grpc.go @@ -13,6 +13,7 @@ import ( "github.com/vito/progrock" "github.com/vito/progrock/graph" "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -23,6 +24,35 @@ type Client struct { var _ bass.Runtime = &Client{} +const GRPCName = "grpc" + +func init() { + RegisterRuntime(GRPCName, NewClient) +} + +type ClientConfig struct { + Target string `json:"target"` +} + +func NewClient(ctx context.Context, _ bass.RuntimePool, cfg *bass.Scope) (bass.Runtime, error) { + var config ClientConfig + if cfg != nil { + if err := cfg.Decode(&config); err != nil { + return nil, fmt.Errorf("buildkit runtime config: %w", err) + } + } + + conn, err := grpc.Dial(config.Target, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return nil, err + } + + return &Client{ + Conn: conn, + RuntimeClient: proto.NewRuntimeClient(conn), + }, nil +} + func (client *Client) Resolve(ctx context.Context, ref bass.ImageRef) (bass.ImageRef, error) { ret := bass.ImageRef{} diff --git a/pkg/runtimes/grpc_test.go b/pkg/runtimes/grpc_test.go new file mode 100644 index 00000000..54e18268 --- /dev/null +++ b/pkg/runtimes/grpc_test.go @@ -0,0 +1,76 @@ +package runtimes_test + +import ( + "context" + "errors" + "net" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + "github.com/vito/bass/pkg/bass" + "github.com/vito/bass/pkg/proto" + "github.com/vito/bass/pkg/runtimes" + "github.com/vito/bass/pkg/runtimes/util/buildkitd" + "github.com/vito/is" + "google.golang.org/grpc" +) + +func TestGRPCRuntime(t *testing.T) { + if testing.Short() { + t.SkipNow() + return + } + + const testInst = "bass-buildkitd-test" + + buildkitd.Remove(context.Background(), testInst) + + config := bass.Bindings{ + "debug": bass.Bool(true), + "installation": bass.String(testInst), + } + + if dir, ok := os.LookupEnv("BASS_TLS_DEPOT"); ok && dir != "" { + config["certs_dir"] = bass.String(dir) + } + + sockPath := filepath.Join(t.TempDir(), "sock") + listener, err := net.Listen("unix", sockPath) + require.NoError(t, err) + + defer listener.Close() + + ctx := context.Background() + + pool, err := runtimes.NewPool(ctx, &bass.Config{ + Runtimes: []bass.RuntimeConfig{ + { + Platform: bass.LinuxPlatform, + Runtime: runtimes.BuildkitName, + }, + }, + }) + is.New(t).NoErr(err) + + srv := grpc.NewServer() + proto.RegisterRuntimeServer(srv, &runtimes.Server{ + Context: ctx, + Runtime: pool.Runtimes[0].Runtime, + }) + + go func() { + if err := srv.Serve(listener); err != nil && !errors.Is(err, net.ErrClosed) { + panic(err) + } + }() + + runtimes.Suite(t, bass.RuntimeConfig{ + Platform: bass.LinuxPlatform, + Runtime: runtimes.GRPCName, + Config: bass.Bindings{ + "target": bass.String("unix://" + sockPath), + }.Scope(), + }) +} From 2b0620c3f6bd60b75bd7307c1c9418dd817dd686 Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Sat, 8 Apr 2023 14:42:13 -0400 Subject: [PATCH 10/16] don't overuse DecodeError this led to pretty confusing errors; it should only be used for decoding Values, not general unmarshaling --- pkg/bass/cache_path.go | 2 +- pkg/bass/errors.go | 2 +- pkg/bass/filesystem_path.go | 2 +- pkg/bass/fspath.go | 2 +- pkg/bass/host_path.go | 2 +- pkg/bass/path.go | 6 +++--- pkg/bass/secret.go | 2 +- pkg/bass/thunk.go | 2 +- pkg/bass/thunk_addr.go | 2 +- pkg/bass/thunk_path.go | 2 +- pkg/bass/thunk_types.go | 18 +++++++++--------- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/pkg/bass/cache_path.go b/pkg/bass/cache_path.go index 68f43537..124e5a46 100644 --- a/pkg/bass/cache_path.go +++ b/pkg/bass/cache_path.go @@ -82,7 +82,7 @@ func (value CachePath) Decode(dest any) error { func (path *CachePath) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.CachePath) if !ok { - return fmt.Errorf("unmarshal proto: %w", DecodeError{msg, path}) + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } path.ID = p.Id diff --git a/pkg/bass/errors.go b/pkg/bass/errors.go index 1120ab2e..36ba7fee 100644 --- a/pkg/bass/errors.go +++ b/pkg/bass/errors.go @@ -64,7 +64,7 @@ func (err BindMismatchError) Error() string { } type DecodeError struct { - Source any + Source Value Destination any } diff --git a/pkg/bass/filesystem_path.go b/pkg/bass/filesystem_path.go index 4d6dee31..18f05375 100644 --- a/pkg/bass/filesystem_path.go +++ b/pkg/bass/filesystem_path.go @@ -163,7 +163,7 @@ func (path *FileOrDirPath) FromValue(val Value) error { func (path *FileOrDirPath) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.FilesystemPath) if !ok { - return DecodeError{msg, path} + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } if p.GetDir() != nil { diff --git a/pkg/bass/fspath.go b/pkg/bass/fspath.go index 6004cbe2..91aa5227 100644 --- a/pkg/bass/fspath.go +++ b/pkg/bass/fspath.go @@ -140,7 +140,7 @@ func (fsp *FSPath) Open(ctx context.Context) (io.ReadCloser, error) { func (value *FSPath) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.LogicalPath) if !ok { - return DecodeError{msg, value} + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } switch x := p.Path.(type) { diff --git a/pkg/bass/host_path.go b/pkg/bass/host_path.go index a015187f..fc90416d 100644 --- a/pkg/bass/host_path.go +++ b/pkg/bass/host_path.go @@ -140,7 +140,7 @@ func (value HostPath) Decode(dest any) error { func (path *HostPath) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.HostPath) if !ok { - return fmt.Errorf("unmarshal proto: %w", DecodeError{msg, path}) + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } path.ContextDir = p.Context diff --git a/pkg/bass/path.go b/pkg/bass/path.go index fe3e5a1e..9ba99b90 100644 --- a/pkg/bass/path.go +++ b/pkg/bass/path.go @@ -86,7 +86,7 @@ func (value DirPath) Decode(dest any) error { func (path *DirPath) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.DirPath) if !ok { - return DecodeError{msg, path} + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } path.Path = p.Path @@ -217,7 +217,7 @@ func (value FilePath) Decode(dest any) error { func (path *FilePath) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.FilePath) if !ok { - return DecodeError{msg, path} + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } path.Path = p.Path @@ -338,7 +338,7 @@ func (value CommandPath) Decode(dest any) error { func (path *CommandPath) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.CommandPath) if !ok { - return DecodeError{msg, path} + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } path.Command = p.Name diff --git a/pkg/bass/secret.go b/pkg/bass/secret.go index ccbc29ad..501b0c79 100644 --- a/pkg/bass/secret.go +++ b/pkg/bass/secret.go @@ -83,7 +83,7 @@ func (value Secret) Decode(dest any) error { func (value *Secret) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.Secret) if !ok { - return fmt.Errorf("unmarshal proto: %w", DecodeError{msg, value}) + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } value.Name = p.Name diff --git a/pkg/bass/thunk.go b/pkg/bass/thunk.go index d1df9ad1..8ed8ef05 100644 --- a/pkg/bass/thunk.go +++ b/pkg/bass/thunk.go @@ -105,7 +105,7 @@ type ThunkTLS struct { func (thunk *Thunk) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.Thunk) if !ok { - return fmt.Errorf("unmarshal proto: %w", DecodeError{msg, thunk}) + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } if p.Image != nil { diff --git a/pkg/bass/thunk_addr.go b/pkg/bass/thunk_addr.go index 7701472b..3873e018 100644 --- a/pkg/bass/thunk_addr.go +++ b/pkg/bass/thunk_addr.go @@ -98,7 +98,7 @@ func (value ThunkAddr) MarshalProto() (proto.Message, error) { func (value *ThunkAddr) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.ThunkAddr) if !ok { - return DecodeError{msg, value} + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } if err := value.Thunk.UnmarshalProto(p.Thunk); err != nil { diff --git a/pkg/bass/thunk_path.go b/pkg/bass/thunk_path.go index f6a8bfdd..0af00c23 100644 --- a/pkg/bass/thunk_path.go +++ b/pkg/bass/thunk_path.go @@ -34,7 +34,7 @@ func (value ThunkPath) Equal(other Value) bool { func (value *ThunkPath) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.ThunkPath) if !ok { - return DecodeError{msg, value} + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } if err := value.Thunk.UnmarshalProto(p.Thunk); err != nil { diff --git a/pkg/bass/thunk_types.go b/pkg/bass/thunk_types.go index 24c84b71..7ef3d02f 100644 --- a/pkg/bass/thunk_types.go +++ b/pkg/bass/thunk_types.go @@ -19,7 +19,7 @@ type ThunkMount struct { func (mount *ThunkMount) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.ThunkMount) if !ok { - return fmt.Errorf("unmarshal proto: %w", DecodeError{msg, mount}) + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } if err := mount.Source.UnmarshalProto(p.GetSource()); err != nil { @@ -90,7 +90,7 @@ var _ ProtoUnmarshaler = (*ImageRef)(nil) func (ref *ImageRef) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.ImageRef) if !ok { - return DecodeError{msg, ref} + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } if err := ref.Platform.UnmarshalProto(p.Platform); err != nil { @@ -179,7 +179,7 @@ func (platform *Platform) FromValue(val Value) error { func (platform *Platform) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.Platform) if !ok { - return DecodeError{msg, platform} + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } platform.OS = p.Os @@ -210,7 +210,7 @@ type ThunkMountSource struct { func (mount *ThunkMountSource) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.ThunkMountSource) if !ok { - return fmt.Errorf("unmarshal proto: %w", DecodeError{msg, mount}) + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } switch x := p.GetSource().(type) { @@ -364,7 +364,7 @@ type ThunkImage struct { func (img *ThunkImage) UnmarshalProto(msg proto.Message) error { protoImage, ok := msg.(*proto.ThunkImage) if !ok { - return DecodeError{msg, img} + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, protoImage) } if protoImage.GetRef() != nil { @@ -559,7 +559,7 @@ type ThunkDir struct { func (dir *ThunkDir) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.ThunkDir) if !ok { - return fmt.Errorf("unmarshal proto: %w", DecodeError{msg, dir}) + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } switch x := p.GetDir().(type) { @@ -729,7 +729,7 @@ var _ ProtoUnmarshaler = (*ImageArchive)(nil) func (ref *ImageArchive) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.ImageArchive) if !ok { - return DecodeError{msg, ref} + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } if err := ref.File.UnmarshalProto(p.GetFile()); err != nil { @@ -791,7 +791,7 @@ var _ ProtoUnmarshaler = (*ImageDockerBuild)(nil) func (ref *ImageDockerBuild) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.ImageDockerBuild) if !ok { - return DecodeError{msg, ref} + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } if err := ref.Platform.UnmarshalProto(p.GetPlatform()); err != nil { @@ -843,7 +843,7 @@ type ImageBuildInput struct { func (ref *ImageBuildInput) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.ImageBuildInput) if !ok { - return DecodeError{msg, ref} + return fmt.Errorf("unmarshal proto: have %T, want %T", msg, p) } switch input := p.GetInput().(type) { From 0dcd7db5644b48efee1409afcf2ab10f764ad18f Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Sat, 8 Apr 2023 14:45:54 -0400 Subject: [PATCH 11/16] clarify secret encoding behavior this is a bit half-baked, just formalling marking the current decision secret values are never encoded, because who knows where they'll end up. in the long term there should be a way to fetch secrets on the runtime side, but that's not implemented yet. for now, we'll just skip the secret tests for the gRPC suite. --- pkg/bass/proto.go | 1 + pkg/bass/secret.go | 2 -- pkg/runtimes/grpc_test.go | 10 +++++-- pkg/runtimes/suite.go | 48 ++++++++++++++++++++++++++---- pkg/runtimes/testdata/secrets.bass | 2 -- proto/bass.proto | 2 ++ 6 files changed, 53 insertions(+), 12 deletions(-) diff --git a/pkg/bass/proto.go b/pkg/bass/proto.go index 913046cf..874803a5 100644 --- a/pkg/bass/proto.go +++ b/pkg/bass/proto.go @@ -146,6 +146,7 @@ func (value String) MarshalProto() (proto.Message, error) { func (value Secret) MarshalProto() (proto.Message, error) { return &proto.Secret{ Name: value.Name, + // NB: don't marshal the value }, nil } diff --git a/pkg/bass/secret.go b/pkg/bass/secret.go index 501b0c79..86f2c84b 100644 --- a/pkg/bass/secret.go +++ b/pkg/bass/secret.go @@ -9,8 +9,6 @@ import ( "google.golang.org/protobuf/encoding/protojson" ) -var Secrets = NewEmptyScope() - func init() { Ground.Set("mask", Func("mask", "[secret name]", func(val String, name Symbol) Secret { diff --git a/pkg/runtimes/grpc_test.go b/pkg/runtimes/grpc_test.go index 54e18268..a34bbec4 100644 --- a/pkg/runtimes/grpc_test.go +++ b/pkg/runtimes/grpc_test.go @@ -8,7 +8,6 @@ import ( "path/filepath" "testing" - "github.com/stretchr/testify/require" "github.com/vito/bass/pkg/bass" "github.com/vito/bass/pkg/proto" "github.com/vito/bass/pkg/runtimes" @@ -38,7 +37,7 @@ func TestGRPCRuntime(t *testing.T) { sockPath := filepath.Join(t.TempDir(), "sock") listener, err := net.Listen("unix", sockPath) - require.NoError(t, err) + is.New(t).NoErr(err) defer listener.Close() @@ -54,6 +53,8 @@ func TestGRPCRuntime(t *testing.T) { }) is.New(t).NoErr(err) + ctx = bass.WithRuntimePool(ctx, pool) + srv := grpc.NewServer() proto.RegisterRuntimeServer(srv, &runtimes.Server{ Context: ctx, @@ -72,5 +73,8 @@ func TestGRPCRuntime(t *testing.T) { Config: bass.Bindings{ "target": bass.String("unix://" + sockPath), }.Scope(), - }) + }, runtimes.SkipSuites( + // secrets don't get sent over gRPC + "secrets.bass", + )) } diff --git a/pkg/runtimes/suite.go b/pkg/runtimes/suite.go index 0e86ce25..9e662432 100644 --- a/pkg/runtimes/suite.go +++ b/pkg/runtimes/suite.go @@ -51,12 +51,17 @@ type SuiteTest struct { //go:embed testdata/write.bass var writeTestContent string -func Suite(t *testing.T, config bass.RuntimeConfig) { +func Suite(t *testing.T, runtimeConfig bass.RuntimeConfig, opts ...SuiteOpt) { ctx := context.Background() + cfg := SuiteConfig{} + for _, opt := range opts { + opt(&cfg) + } + pool, err := NewPool(ctx, &bass.Config{ Runtimes: []bass.RuntimeConfig{ - config, + runtimeConfig, }, }) is.New(t).NoErr(err) @@ -241,8 +246,7 @@ func Suite(t *testing.T, config bass.RuntimeConfig) { Result: bass.Bool(true), }, { - File: "secrets.bass", - Result: bass.Null{}, + File: "secrets.bass", Bindings: bass.Bindings{ "assert-export-does-not-contain-secret": bass.Func("assert-export-does-not-contain-secret", "[thunk]", func(ctx context.Context, thunk bass.Thunk) error { pool, err := bass.RuntimePoolFromContext(ctx) @@ -305,6 +309,11 @@ func Suite(t *testing.T, config bass.RuntimeConfig) { } { test := test t.Run(filepath.Base(test.File), func(t *testing.T) { + if cfg.ShouldSkip(test.File) { + t.Skipf("skipping %s", test.File) + return + } + is := is.New(t) t.Parallel() @@ -318,12 +327,41 @@ func Suite(t *testing.T, config bass.RuntimeConfig) { } else { is.NoErr(err) is.True(res != nil) - basstest.Equal(t, res, test.Result) + if test.Result != nil { + basstest.Equal(t, res, test.Result) + } } }) } } +type SuiteConfig struct { + Skip map[string]struct{} +} + +func (cfg SuiteConfig) ShouldSkip(suite string) bool { + if cfg.Skip == nil { + return false + } + + _, found := cfg.Skip[suite] + return found +} + +type SuiteOpt func(*SuiteConfig) + +func SkipSuites(suites ...string) SuiteOpt { + return func(cfg *SuiteConfig) { + if cfg.Skip == nil { + cfg.Skip = map[string]struct{}{} + } + + for _, suite := range suites { + cfg.Skip[suite] = struct{}{} + } + } +} + func (test SuiteTest) Run(ctx context.Context, t *testing.T, env *bass.Scope) (val bass.Value, err error) { is := is.New(t) diff --git a/pkg/runtimes/testdata/secrets.bass b/pkg/runtimes/testdata/secrets.bass index ca55cf1d..34cb6afb 100644 --- a/pkg/runtimes/testdata/secrets.bass +++ b/pkg/runtimes/testdata/secrets.bass @@ -26,5 +26,3 @@ (map assert-export-does-not-contain-secret [stdin-secret env-secret file-secret]) - -null diff --git a/proto/bass.proto b/proto/bass.proto index 1012f1d5..618b3465 100644 --- a/proto/bass.proto +++ b/proto/bass.proto @@ -162,6 +162,8 @@ message CachePath { message Secret { string name = 1; + // NB: secrets values are intentionally omitted. + // string secret = 2; }; message CommandPath { From 5d33218f044e01343b48e530f46a3c84230b81b1 Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Sat, 8 Apr 2023 16:20:36 -0400 Subject: [PATCH 12/16] restructure thunk/image/entrypoint modeling * (resolve), (docker-build), and the new (oci-load) return a thunk instead of an "image" "Image" was a sort of nebulous type; it was never its own type, it was really just a scope that had a certain set of fields. This was awkward because it meant you couldn't do the equivalent to this: FROM golang ENTRYPOINT ["go", "build"] But now you can, because it returns a thunk! (-> (linux/golang) (with-entrypoint ["go" "build"])) Same goes for (docker-build), and (oci-load) has been added and follows the same pattern. The returned thunk has no arguments set; it only has an image. More on this in the next point. * If you tell a thunk to run, and the thunk has no arguments, it will inherit the ENTRYPOINT and CMD from its base image. This applies to (run), (read), thunk paths, and thunk addresses. It does NOT apply to (publish) or (export) as the intention is to publish the ENTRYPOINT/CMD, not run it. * Now that (resolve) returns a thunk you'll also notice much smaller bass.lock files (thunks get their own marshaling, images marshaled as a scope, which is pretty verbose). On the other hand, you'll also have to remove your bass.lock files or bass --bump them since the old stored return value is no longer valid. * Stop relying on nil vs. [] distinction for clearing ENTRYPOINT/CMD since it's not possible to represent with protobufs. * Exposed ports are now included in published image config. --- bass/bass.lock | 354 +++++++++------- demos/bass.lock | 0 demos/git-lib.bass | 2 +- demos/git-lib.lock | 116 ++++++ pkg/bass/encoding_test.go | 6 +- pkg/bass/fake_runtime_test.go | 6 +- pkg/bass/ground.go | 4 +- pkg/bass/proto.go | 27 +- pkg/bass/runtime.go | 2 +- pkg/bass/thunk.go | 23 +- pkg/bass/thunk_path.go | 2 + pkg/bass/thunk_types.go | 41 +- pkg/proto/bass.pb.go | 399 ++++++++++--------- pkg/proto/runtime.pb.go | 42 +- pkg/proto/runtime_grpc.pb.go | 10 +- pkg/runtimes/buildkit.go | 53 ++- pkg/runtimes/dagger.go | 32 +- pkg/runtimes/dagger_test.go | 9 +- pkg/runtimes/grpc.go | 15 +- pkg/runtimes/suite.go | 23 +- pkg/runtimes/testdata/addrs.bass | 34 +- pkg/runtimes/testdata/bass.lock | 130 +----- pkg/runtimes/testdata/docker-build.bass | 50 ++- pkg/runtimes/testdata/entrypoints.bass | 67 ++-- pkg/runtimes/testdata/lib/oci.bass | 25 ++ pkg/runtimes/testdata/oci-archive-image.bass | 15 +- pkg/runtimes/testdata/tls.bass | 4 +- proto/bass.proto | 4 + proto/runtime.proto | 2 +- std/run.bass | 28 +- 30 files changed, 909 insertions(+), 616 deletions(-) delete mode 100644 demos/bass.lock create mode 100644 demos/git-lib.lock create mode 100644 pkg/runtimes/testdata/lib/oci.bass diff --git a/bass/bass.lock b/bass/bass.lock index 1611e3f9..da6fb176 100644 --- a/bass/bass.lock +++ b/bass/bass.lock @@ -49,52 +49,72 @@ memos: { } } output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine/git" + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "alpine/git" + tag: "latest" + digest: "sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2" } } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "architecture" - value: { - string: { - value: "amd64" + } + } + } + results: { + input: { + array: { + values: { + object: { + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } } } } - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } + } + bindings: { + symbol: "repository" + value: { + string: { + value: "ubuntu" } } } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } } } } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2" + } + } + output: { + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "ubuntu" + tag: "latest" + digest: "sha256:67211c14fa74f070d27cc59d69a7fa9aeff8e28ea118ef3babc295a0428a6d21" } } } @@ -124,7 +144,7 @@ memos: { symbol: "repository" value: { string: { - value: "ubuntu" + value: "alpine" } } } @@ -141,52 +161,72 @@ memos: { } } output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "ubuntu" + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "alpine" + tag: "latest" + digest: "sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126" } } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "architecture" - value: { - string: { - value: "amd64" + } + } + } + results: { + input: { + array: { + values: { + object: { + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } } } } - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } + } + bindings: { + symbol: "repository" + value: { + string: { + value: "squareup/certstrap" } } } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } } } } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:67211c14fa74f070d27cc59d69a7fa9aeff8e28ea118ef3babc295a0428a6d21" + } + } + output: { + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "squareup/certstrap" + tag: "latest" + digest: "sha256:c18a2389cf102a78ed6b42a2ae56ab81d898de30cdf1aca79a16bec15b22f7f2" } } } @@ -216,7 +256,7 @@ memos: { symbol: "repository" value: { string: { - value: "alpine" + value: "alpine/git" } } } @@ -224,7 +264,7 @@ memos: { symbol: "tag" value: { string: { - value: "latest" + value: "2.36.3" } } } @@ -233,52 +273,72 @@ memos: { } } output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine" + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "alpine/git" + tag: "2.36.3" + digest: "sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2" } } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "architecture" - value: { - string: { - value: "amd64" + } + } + } + results: { + input: { + array: { + values: { + object: { + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } } } } - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } + } + bindings: { + symbol: "repository" + value: { + string: { + value: "registry" } } } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } } } } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126" + } + } + output: { + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "registry" + tag: "latest" + digest: "sha256:8c51be2f669c82da8015017ff1eae5e5155fcf707ba914c5c7b798fbeb03b50c" } } } @@ -308,7 +368,7 @@ memos: { symbol: "repository" value: { string: { - value: "squareup/certstrap" + value: "busybox" } } } @@ -325,52 +385,72 @@ memos: { } } output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "squareup/certstrap" + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "busybox" + tag: "latest" + digest: "sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" } } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "architecture" - value: { - string: { - value: "amd64" + } + } + } + results: { + input: { + array: { + values: { + object: { + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } } } } - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } + } + bindings: { + symbol: "repository" + value: { + string: { + value: "hello-world" } } } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } } } } - bindings: { - symbol: "digest" - value: { - string: { - value: "sha256:c18a2389cf102a78ed6b42a2ae56ab81d898de30cdf1aca79a16bec15b22f7f2" + } + } + output: { + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "hello-world" + tag: "latest" + digest: "sha256:ffb13da98453e0f04d33a6eee5bb8e46ee50d08ebe17735fc0779d0349e889e9" } } } @@ -420,7 +500,7 @@ memos: { } output: { string: { - value: "06cbb3adb6ceb9f54e6d747cb56c8f738e893fb1" + value: "6ca3f15d70b739a7929886e20b61dbc4cbdc4e22" } } } diff --git a/demos/bass.lock b/demos/bass.lock deleted file mode 100644 index e69de29b..00000000 diff --git a/demos/git-lib.bass b/demos/git-lib.bass index f65bad76..aa40c206 100644 --- a/demos/git-lib.bass +++ b/demos/git-lib.bass @@ -1,7 +1,7 @@ ; image and git path resolution will be cached here. ; ; images store digests, git paths store shas. -(def *memos* *dir*/bass.lock) +(def *memos* *dir*/git-lib.lock) (use (.git (linux/alpine/git)) (git:github/vito/tabs/ref/main/wget.bass)) diff --git a/demos/git-lib.lock b/demos/git-lib.lock new file mode 100644 index 00000000..cc5b8024 --- /dev/null +++ b/demos/git-lib.lock @@ -0,0 +1,116 @@ +memos: { + module: { + args: { + command_path: { + name: "run" + } + } + } + calls: { + binding: "resolve" + results: { + input: { + array: { + values: { + object: { + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } + } + } + } + } + bindings: { + symbol: "repository" + value: { + string: { + value: "alpine/git" + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } + } + } + } + } + } + output: { + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" + } + repository: "alpine/git" + tag: "latest" + digest: "sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2" + } + } + } + } + } + } +} +memos: { + module: { + args: { + command_path: { + name: "git" + } + } + stdin: { + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" + } + repository: "alpine/git" + tag: "latest" + digest: "sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2" + } + } + } + } + } + calls: { + binding: "ls-remote" + results: { + input: { + array: { + values: { + string: { + value: "https://github.com/vito/tabs" + } + } + values: { + string: { + value: "main" + } + } + } + } + output: { + string: { + value: "6ca3f15d70b739a7929886e20b61dbc4cbdc4e22" + } + } + } + } +} diff --git a/pkg/bass/encoding_test.go b/pkg/bass/encoding_test.go index 9d146afb..f76393a6 100644 --- a/pkg/bass/encoding_test.go +++ b/pkg/bass/encoding_test.go @@ -239,6 +239,10 @@ var validThunkImageArchives = []bass.ImageArchive{ }, } +func ptr[T any](v T) *T { + return &v +} + var validThunkImageDockerBuilds = []bass.ImageDockerBuild{ { Platform: bass.Platform{ @@ -251,7 +255,7 @@ var validThunkImageDockerBuilds = []bass.ImageDockerBuild{ Path: bass.ParseFileOrDirPath("thunk/dir/"), }, }, - Dockerfile: bass.NewFilePath("my-dockerfile"), + Dockerfile: ptr(bass.NewFilePath("my-dockerfile")), Target: "target", Args: bass.Bindings{ "arg1": bass.String("value1"), diff --git a/pkg/bass/fake_runtime_test.go b/pkg/bass/fake_runtime_test.go index 930059bb..9a46c0fe 100644 --- a/pkg/bass/fake_runtime_test.go +++ b/pkg/bass/fake_runtime_test.go @@ -20,8 +20,10 @@ type ExportPath struct { FS fstest.MapFS } -func (fake *FakeRuntime) Resolve(context.Context, bass.ImageRef) (bass.ImageRef, error) { - return bass.ImageRef{}, fmt.Errorf("Resolve unimplemented") +var _ bass.Runtime = &FakeRuntime{} + +func (fake *FakeRuntime) Resolve(context.Context, bass.ImageRef) (bass.Thunk, error) { + return bass.Thunk{}, fmt.Errorf("Resolve unimplemented") } func (fake *FakeRuntime) Run(context.Context, bass.Thunk) error { diff --git a/pkg/bass/ground.go b/pkg/bass/ground.go index cc42b116..30ccce6c 100644 --- a/pkg/bass/ground.go +++ b/pkg/bass/ground.go @@ -731,10 +731,10 @@ func init() { `=> (load (.strings))`) Ground.Set("resolve", - Func("resolve", "[platform ref]", func(ctx context.Context, ref ImageRef) (ImageRef, error) { + Func("resolve", "[platform ref]", func(ctx context.Context, ref ImageRef) (Thunk, error) { runtime, err := RuntimeFromContext(ctx, ref.Platform) if err != nil { - return ImageRef{}, err + return Thunk{}, err } return runtime.Resolve(ctx, ref) diff --git a/pkg/bass/proto.go b/pkg/bass/proto.go index 874803a5..9707a932 100644 --- a/pkg/bass/proto.go +++ b/pkg/bass/proto.go @@ -322,7 +322,7 @@ func (value CachePath) MarshalProto() (proto.Message, error) { } func (value Thunk) MarshalProto() (proto.Message, error) { - thunk := &proto.Thunk{ + pThunk := &proto.Thunk{ Insecure: value.Insecure, } @@ -332,7 +332,7 @@ func (value Thunk) MarshalProto() (proto.Message, error) { return nil, fmt.Errorf("image: %w", err) } - thunk.Image = ti.(*proto.ThunkImage) + pThunk.Image = ti.(*proto.ThunkImage) } for i, v := range value.Args { @@ -341,16 +341,21 @@ func (value Thunk) MarshalProto() (proto.Message, error) { return nil, fmt.Errorf("arg %d: %w", i, err) } - thunk.Args = append(thunk.Args, pv) + pThunk.Args = append(pThunk.Args, pv) } + pThunk.Entrypoint = value.Entrypoint + pThunk.ClearEntrypoint = value.ClearEntrypoint + pThunk.DefaultArgs = value.DefaultArgs + pThunk.ClearDefaultArgs = value.ClearDefaultArgs + for i, v := range value.Stdin { pv, err := MarshalProto(v) if err != nil { return nil, fmt.Errorf("stdin %d: %w", i, err) } - thunk.Stdin = append(thunk.Stdin, pv) + pThunk.Stdin = append(pThunk.Stdin, pv) } if value.Env != nil { @@ -360,7 +365,7 @@ func (value Thunk) MarshalProto() (proto.Message, error) { return fmt.Errorf("%s: %w", sym, err) } - thunk.Env = append(thunk.Env, &proto.Binding{ + pThunk.Env = append(pThunk.Env, &proto.Binding{ Symbol: string(sym), Value: pv, }) @@ -377,7 +382,7 @@ func (value Thunk) MarshalProto() (proto.Message, error) { return nil, fmt.Errorf("dir: %w", err) } - thunk.Dir = di.(*proto.ThunkDir) + pThunk.Dir = di.(*proto.ThunkDir) } for _, m := range value.Mounts { @@ -386,7 +391,7 @@ func (value Thunk) MarshalProto() (proto.Message, error) { return nil, fmt.Errorf("dir: %w", err) } - thunk.Mounts = append(thunk.Mounts, pm.(*proto.ThunkMount)) + pThunk.Mounts = append(pThunk.Mounts, pm.(*proto.ThunkMount)) } if value.Labels != nil { @@ -396,7 +401,7 @@ func (value Thunk) MarshalProto() (proto.Message, error) { return fmt.Errorf("%s: %w", sym, err) } - thunk.Labels = append(thunk.Labels, &proto.Binding{ + pThunk.Labels = append(pThunk.Labels, &proto.Binding{ Symbol: string(sym), Value: lv, }) @@ -408,7 +413,7 @@ func (value Thunk) MarshalProto() (proto.Message, error) { } for _, port := range value.Ports { - thunk.Ports = append(thunk.Ports, &proto.ThunkPort{ + pThunk.Ports = append(pThunk.Ports, &proto.ThunkPort{ Name: port.Name, Port: int32(port.Port), }) @@ -425,13 +430,13 @@ func (value Thunk) MarshalProto() (proto.Message, error) { return nil, fmt.Errorf("marshal cert: %w", err) } - thunk.Tls = &proto.ThunkTLS{ + pThunk.Tls = &proto.ThunkTLS{ Cert: cert.(*proto.FilePath), Key: key.(*proto.FilePath), } } - return thunk, nil + return pThunk, nil } func (value ThunkPath) MarshalProto() (proto.Message, error) { diff --git a/pkg/bass/runtime.go b/pkg/bass/runtime.go index c13ab840..ab25c0ac 100644 --- a/pkg/bass/runtime.go +++ b/pkg/bass/runtime.go @@ -13,7 +13,7 @@ type RuntimePool interface { } type Runtime interface { - Resolve(context.Context, ImageRef) (ImageRef, error) + Resolve(context.Context, ImageRef) (Thunk, error) Run(context.Context, Thunk) error Read(context.Context, io.Writer, Thunk) error Export(context.Context, io.Writer, Thunk) error diff --git a/pkg/bass/thunk.go b/pkg/bass/thunk.go index 8ed8ef05..de0d258c 100644 --- a/pkg/bass/thunk.go +++ b/pkg/bass/thunk.go @@ -22,6 +22,9 @@ import ( type Thunk struct { // Image specifies the OCI image in which to run the thunk. + // + // If not present, the thunk is a native "Bass" thunk representing a module + // to load. Image *ThunkImage `json:"image,omitempty"` // Insecure may be set to true to enable running the thunk with elevated @@ -29,6 +32,9 @@ type Thunk struct { Insecure bool `json:"insecure,omitempty"` // Args is a list of string or path arguments. + // + // If left empty, and the thunk is forced to run via (run), (read), or an + // output path, the parent Entrypoint and DefaultArgs are used. Args []Value `json:"args,omitempty"` // Stdin is a list of arbitrary values, which may contain paths, to pass to @@ -83,13 +89,15 @@ type Thunk struct { // A null value inherits from the parent. An empty slice removes it. // // Note that Bass thunks don't actually use the entrypoint themselves. - Entrypoint []string `json:"entrypoint,omitempty"` + Entrypoint []string `json:"entrypoint,omitempty"` + ClearEntrypoint bool `json:"clear_entrypoint,omitempty"` // DefaultArgs configures a command and arguments to used when the published // container runs. // // Note that Bass thunks don't actually use the default args themselves. - DefaultArgs []string `json:"default_args,omitempty"` + DefaultArgs []string `json:"default_args,omitempty"` + ClearDefaultArgs bool `json:"clear_default_args,omitempty"` } type ThunkPort struct { @@ -126,6 +134,11 @@ func (thunk *Thunk) UnmarshalProto(msg proto.Message) error { thunk.Args = append(thunk.Args, val) } + thunk.Entrypoint = p.Entrypoint + thunk.ClearEntrypoint = p.ClearEntrypoint + thunk.DefaultArgs = p.DefaultArgs + thunk.ClearDefaultArgs = p.ClearDefaultArgs + for i, stdin := range p.Stdin { val, err := FromProto(stdin) if err != nil { @@ -430,12 +443,18 @@ func (thunk Thunk) WithImage(image ThunkImage) Thunk { // WithEntrypoint sets the thunk's entrypoint. func (thunk Thunk) WithEntrypoint(entrypoint []string) Thunk { + if len(entrypoint) == 0 { + thunk.ClearEntrypoint = true + } thunk.Entrypoint = entrypoint return thunk } // WithDefaultArgs sets the thunk's default arguments. func (thunk Thunk) WithDefaultArgs(args []string) Thunk { + if len(args) == 0 { + thunk.ClearDefaultArgs = true + } thunk.DefaultArgs = args return thunk } diff --git a/pkg/bass/thunk_path.go b/pkg/bass/thunk_path.go index 0af00c23..30990b49 100644 --- a/pkg/bass/thunk_path.go +++ b/pkg/bass/thunk_path.go @@ -159,6 +159,8 @@ func (path ThunkPath) CachePath(ctx context.Context, dest string) (string, error func (path ThunkPath) Open(ctx context.Context) (io.ReadCloser, error) { platform := path.Thunk.Platform() if platform == nil { + // TODO: why not? it could be relative to `*dir*`. the bass thunk could + // even redefine it. return nil, fmt.Errorf("cannot open bass thunk path: %s", path) } diff --git a/pkg/bass/thunk_types.go b/pkg/bass/thunk_types.go index 7ef3d02f..58b5ce68 100644 --- a/pkg/bass/thunk_types.go +++ b/pkg/bass/thunk_types.go @@ -68,6 +68,14 @@ type ImageRef struct { Digest string `json:"digest,omitempty"` } +func (ref ImageRef) Thunk() Thunk { + return Thunk{ + Image: &ThunkImage{ + Ref: &ref, + }, + } +} + func (ref ImageRef) Ref() (string, error) { if ref.Repository.Static == "" { return "", fmt.Errorf("ref does not refer to a static repository") @@ -776,7 +784,7 @@ type ImageDockerBuild struct { Context ImageBuildInput `json:"docker_build"` // Path to a Dockerfile to use within the context. - Dockerfile FilePath `json:"dockerfile,omitempty"` + Dockerfile *FilePath `json:"dockerfile,omitempty"` // Target witin the Dockerfile to build. Target string `json:"target,omitempty"` @@ -803,7 +811,8 @@ func (ref *ImageDockerBuild) UnmarshalProto(msg proto.Message) error { } if p.GetDockerfile() != "" { - ref.Dockerfile = NewFilePath(p.GetDockerfile()) + df := NewFilePath(p.GetDockerfile()) + ref.Dockerfile = &df } ref.Target = p.GetTarget() @@ -831,6 +840,34 @@ func (ref ImageDockerBuild) MarshalProto() (proto.Message, error) { pv.Context = i.(*proto.ImageBuildInput) + if ref.Dockerfile != nil { + df := ref.Dockerfile.String() + pv.Dockerfile = &df + } + + if ref.Target != "" { + pv.Target = &ref.Target + } + + if ref.Args != nil { + err := ref.Args.Each(func(k Symbol, v Value) error { + var str string + if err := v.Decode(&str); err != nil { + return fmt.Errorf("build arg %q: %w", k, err) + } + + pv.Args = append(pv.Args, &proto.BuildArg{ + Name: k.String(), + Value: str, + }) + + return nil + }) + if err != nil { + return nil, err + } + } + return pv, nil } diff --git a/pkg/proto/bass.pb.go b/pkg/proto/bass.pb.go index 1372d94d..496b1e28 100644 --- a/pkg/proto/bass.pb.go +++ b/pkg/proto/bass.pb.go @@ -302,16 +302,20 @@ type Thunk struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Image *ThunkImage `protobuf:"bytes,1,opt,name=image,proto3" json:"image,omitempty"` - Insecure bool `protobuf:"varint,2,opt,name=insecure,proto3" json:"insecure,omitempty"` - Args []*Value `protobuf:"bytes,4,rep,name=args,proto3" json:"args,omitempty"` - Stdin []*Value `protobuf:"bytes,5,rep,name=stdin,proto3" json:"stdin,omitempty"` - Env []*Binding `protobuf:"bytes,6,rep,name=env,proto3" json:"env,omitempty"` - Dir *ThunkDir `protobuf:"bytes,7,opt,name=dir,proto3" json:"dir,omitempty"` - Mounts []*ThunkMount `protobuf:"bytes,8,rep,name=mounts,proto3" json:"mounts,omitempty"` - Labels []*Binding `protobuf:"bytes,9,rep,name=labels,proto3" json:"labels,omitempty"` - Ports []*ThunkPort `protobuf:"bytes,10,rep,name=ports,proto3" json:"ports,omitempty"` - Tls *ThunkTLS `protobuf:"bytes,11,opt,name=tls,proto3" json:"tls,omitempty"` + Image *ThunkImage `protobuf:"bytes,1,opt,name=image,proto3" json:"image,omitempty"` + Insecure bool `protobuf:"varint,2,opt,name=insecure,proto3" json:"insecure,omitempty"` + Args []*Value `protobuf:"bytes,4,rep,name=args,proto3" json:"args,omitempty"` + Stdin []*Value `protobuf:"bytes,5,rep,name=stdin,proto3" json:"stdin,omitempty"` + Env []*Binding `protobuf:"bytes,6,rep,name=env,proto3" json:"env,omitempty"` + Dir *ThunkDir `protobuf:"bytes,7,opt,name=dir,proto3" json:"dir,omitempty"` + Mounts []*ThunkMount `protobuf:"bytes,8,rep,name=mounts,proto3" json:"mounts,omitempty"` + Labels []*Binding `protobuf:"bytes,9,rep,name=labels,proto3" json:"labels,omitempty"` + Ports []*ThunkPort `protobuf:"bytes,10,rep,name=ports,proto3" json:"ports,omitempty"` + Tls *ThunkTLS `protobuf:"bytes,11,opt,name=tls,proto3" json:"tls,omitempty"` + Entrypoint []string `protobuf:"bytes,12,rep,name=entrypoint,proto3" json:"entrypoint,omitempty"` + ClearEntrypoint bool `protobuf:"varint,13,opt,name=clear_entrypoint,json=clearEntrypoint,proto3" json:"clear_entrypoint,omitempty"` + DefaultArgs []string `protobuf:"bytes,14,rep,name=default_args,json=defaultArgs,proto3" json:"default_args,omitempty"` + ClearDefaultArgs bool `protobuf:"varint,15,opt,name=clear_default_args,json=clearDefaultArgs,proto3" json:"clear_default_args,omitempty"` } func (x *Thunk) Reset() { @@ -416,6 +420,34 @@ func (x *Thunk) GetTls() *ThunkTLS { return nil } +func (x *Thunk) GetEntrypoint() []string { + if x != nil { + return x.Entrypoint + } + return nil +} + +func (x *Thunk) GetClearEntrypoint() bool { + if x != nil { + return x.ClearEntrypoint + } + return false +} + +func (x *Thunk) GetDefaultArgs() []string { + if x != nil { + return x.DefaultArgs + } + return nil +} + +func (x *Thunk) GetClearDefaultArgs() bool { + if x != nil { + return x.ClearDefaultArgs + } + return false +} + type ThunkAddr struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2440,7 +2472,7 @@ var file_bass_proto_rawDesc = []byte{ 0x30, 0x0a, 0x0a, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x63, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, - 0x68, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xec, 0x02, 0x0a, 0x05, 0x54, + 0x68, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x88, 0x04, 0x0a, 0x05, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x26, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, @@ -2463,99 +2495,84 @@ var file_bass_proto_rawDesc = []byte{ 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x20, 0x0a, 0x03, 0x74, 0x6c, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, - 0x6b, 0x54, 0x4c, 0x53, 0x52, 0x03, 0x74, 0x6c, 0x73, 0x22, 0x5a, 0x0a, 0x09, 0x54, 0x68, 0x75, - 0x6e, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x12, 0x21, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, - 0x6e, 0x6b, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x16, 0x0a, - 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, - 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x33, 0x0a, 0x09, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x6f, - 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x50, 0x0a, 0x08, 0x54, 0x68, - 0x75, 0x6e, 0x6b, 0x54, 0x4c, 0x53, 0x12, 0x22, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, - 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x12, 0x20, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, - 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xcb, 0x01, 0x0a, - 0x0a, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x03, 0x72, - 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, - 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, 0x48, 0x00, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, - 0x23, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, - 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x48, 0x00, 0x52, 0x05, 0x74, - 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x2e, 0x0a, 0x07, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x49, 0x6d, 0x61, - 0x67, 0x65, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x48, 0x00, 0x52, 0x07, 0x61, 0x72, 0x63, - 0x68, 0x69, 0x76, 0x65, 0x12, 0x3b, 0x0a, 0x0c, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x62, - 0x75, 0x69, 0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x61, 0x73, - 0x73, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x42, 0x75, 0x69, - 0x6c, 0x64, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, - 0x64, 0x42, 0x07, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0xfb, 0x01, 0x0a, 0x08, 0x49, - 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, 0x12, 0x2a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, - 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, - 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, - 0x6f, 0x72, 0x6d, 0x12, 0x20, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, - 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x29, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, - 0x50, 0x61, 0x74, 0x68, 0x42, 0x02, 0x18, 0x01, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, - 0x12, 0x25, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, - 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x48, - 0x00, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x15, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x03, 0x74, 0x61, 0x67, 0x88, 0x01, 0x01, 0x12, 0x1b, - 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, - 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x74, 0x61, 0x67, 0x42, 0x09, 0x0a, - 0x07, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x22, 0x7e, 0x0a, 0x0c, 0x49, 0x6d, 0x61, 0x67, - 0x65, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, 0x2a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, - 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, - 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, - 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x23, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, - 0x61, 0x74, 0x68, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x15, 0x0a, 0x03, 0x74, 0x61, 0x67, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67, 0x88, 0x01, 0x01, - 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x74, 0x61, 0x67, 0x22, 0xef, 0x01, 0x0a, 0x10, 0x49, 0x6d, 0x61, - 0x67, 0x65, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x2a, 0x0a, - 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, - 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x2f, 0x0a, 0x07, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x62, 0x61, 0x73, - 0x73, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x70, 0x75, - 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x23, 0x0a, 0x0a, 0x64, 0x6f, - 0x63, 0x6b, 0x65, 0x72, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, - 0x52, 0x0a, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x66, 0x69, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, - 0x1b, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, - 0x01, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x04, - 0x61, 0x72, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, - 0x73, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x41, 0x72, 0x67, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, - 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x66, 0x69, 0x6c, 0x65, 0x42, - 0x09, 0x0a, 0x07, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x98, 0x01, 0x0a, 0x0f, 0x49, - 0x6d, 0x61, 0x67, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x27, - 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, - 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, - 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x48, 0x6f, 0x73, - 0x74, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x2d, 0x0a, - 0x07, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, - 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, - 0x68, 0x48, 0x00, 0x52, 0x07, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x42, 0x07, 0x0a, 0x05, - 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x34, 0x0a, 0x08, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x41, 0x72, - 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2e, 0x0a, 0x08, 0x50, - 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x6f, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x22, 0x87, 0x01, 0x0a, 0x08, - 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x44, 0x69, 0x72, 0x12, 0x25, 0x0a, 0x05, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x44, - 0x69, 0x72, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x12, - 0x27, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, - 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, - 0x00, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, - 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x48, 0x6f, - 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x42, 0x05, - 0x0a, 0x03, 0x64, 0x69, 0x72, 0x22, 0xeb, 0x01, 0x0a, 0x10, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, - 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x05, 0x74, 0x68, + 0x6b, 0x54, 0x4c, 0x53, 0x52, 0x03, 0x74, 0x6c, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x65, + 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6c, 0x65, + 0x61, 0x72, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0f, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, + 0x61, 0x72, 0x67, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x6c, 0x65, 0x61, 0x72, + 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x0f, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x41, 0x72, 0x67, 0x73, 0x22, 0x5a, 0x0a, 0x09, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x41, 0x64, + 0x64, 0x72, 0x12, 0x21, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x52, 0x05, + 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x22, 0x33, 0x0a, 0x09, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x50, 0x0a, 0x08, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x54, + 0x4c, 0x53, 0x12, 0x22, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, + 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x12, 0x20, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x50, + 0x61, 0x74, 0x68, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xcb, 0x01, 0x0a, 0x0a, 0x54, 0x68, 0x75, + 0x6e, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x49, 0x6d, 0x61, 0x67, + 0x65, 0x52, 0x65, 0x66, 0x48, 0x00, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x23, 0x0a, 0x05, 0x74, + 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, + 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x48, 0x00, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, + 0x12, 0x2e, 0x0a, 0x07, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x41, 0x72, + 0x63, 0x68, 0x69, 0x76, 0x65, 0x48, 0x00, 0x52, 0x07, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, + 0x12, 0x3b, 0x0a, 0x0c, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x49, 0x6d, + 0x61, 0x67, 0x65, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x48, 0x00, + 0x52, 0x0b, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x42, 0x07, 0x0a, + 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0xfb, 0x01, 0x0a, 0x08, 0x49, 0x6d, 0x61, 0x67, 0x65, + 0x52, 0x65, 0x66, 0x12, 0x2a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x50, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, + 0x20, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, + 0x79, 0x12, 0x29, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, + 0x42, 0x02, 0x18, 0x01, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x04, + 0x61, 0x64, 0x64, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, + 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x48, 0x00, 0x52, 0x04, 0x61, + 0x64, 0x64, 0x72, 0x12, 0x15, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x01, 0x52, 0x03, 0x74, 0x61, 0x67, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x64, 0x69, + 0x67, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x06, 0x64, 0x69, + 0x67, 0x65, 0x73, 0x74, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x74, 0x61, 0x67, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x64, 0x69, + 0x67, 0x65, 0x73, 0x74, 0x22, 0x7e, 0x0a, 0x0c, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x41, 0x72, 0x63, + 0x68, 0x69, 0x76, 0x65, 0x12, 0x2a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x50, 0x6c, + 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, + 0x12, 0x23, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, + 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x52, + 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x15, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67, 0x88, 0x01, 0x01, 0x42, 0x06, 0x0a, 0x04, + 0x5f, 0x74, 0x61, 0x67, 0x22, 0xef, 0x01, 0x0a, 0x10, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x6f, + 0x63, 0x6b, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x2a, 0x0a, 0x08, 0x70, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, + 0x73, 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x2f, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x49, 0x6d, + 0x61, 0x67, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x07, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x23, 0x0a, 0x0a, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, + 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x6f, + 0x63, 0x6b, 0x65, 0x72, 0x66, 0x69, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x06, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, + 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x42, 0x75, + 0x69, 0x6c, 0x64, 0x41, 0x72, 0x67, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x42, 0x0d, 0x0a, 0x0b, + 0x5f, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x98, 0x01, 0x0a, 0x0f, 0x49, 0x6d, 0x61, 0x67, 0x65, + 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x27, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, @@ -2563,82 +2580,106 @@ var file_bass_proto_rawDesc = []byte{ 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x07, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, - 0x07, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x05, 0x63, 0x61, 0x63, 0x68, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x43, - 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x63, 0x61, 0x63, 0x68, - 0x65, 0x12, 0x26, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0c, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x48, - 0x00, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x22, 0x6a, 0x0a, 0x0a, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x6f, - 0x75, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, - 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, - 0x2c, 0x0a, 0x05, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x23, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x33, 0x0a, - 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x29, 0x0a, 0x08, 0x62, 0x69, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, - 0x2e, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x73, 0x22, 0x44, 0x0a, 0x07, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, - 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x12, 0x21, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x06, 0x0a, 0x04, 0x4e, 0x75, 0x6c, 0x6c, - 0x22, 0x1c, 0x0a, 0x04, 0x42, 0x6f, 0x6f, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1b, - 0x0a, 0x03, 0x49, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1e, 0x0a, 0x06, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x45, 0x0a, 0x09, 0x43, - 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, - 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x22, 0x1c, 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x07, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x42, 0x07, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, + 0x74, 0x22, 0x34, 0x0a, 0x08, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x41, 0x72, 0x67, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2e, 0x0a, 0x08, 0x50, 0x6c, 0x61, 0x74, 0x66, + 0x6f, 0x72, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x6f, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x22, 0x87, 0x01, 0x0a, 0x08, 0x54, 0x68, 0x75, 0x6e, + 0x6b, 0x44, 0x69, 0x72, 0x12, 0x25, 0x0a, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x44, 0x69, 0x72, 0x50, 0x61, + 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x05, 0x74, + 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, + 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x74, + 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x61, + 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x42, 0x05, 0x0a, 0x03, 0x64, 0x69, + 0x72, 0x22, 0xeb, 0x01, 0x0a, 0x10, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x6f, 0x75, 0x6e, 0x74, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, + 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, + 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, + 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x07, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, + 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x07, 0x6c, 0x6f, 0x67, + 0x69, 0x63, 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x05, 0x63, 0x61, 0x63, 0x68, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, + 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x63, 0x61, 0x63, 0x68, 0x65, 0x12, 0x26, 0x0a, + 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x48, 0x00, 0x52, 0x06, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, + 0x6a, 0x0a, 0x0a, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, 0x0a, + 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2c, 0x0a, + 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, + 0x61, 0x74, 0x68, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x2c, 0x0a, 0x05, 0x41, + 0x72, 0x72, 0x61, 0x79, 0x12, 0x23, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x33, 0x0a, 0x06, 0x4f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x12, 0x29, 0x0a, 0x08, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x42, 0x69, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x44, + 0x0a, 0x07, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6d, + 0x62, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x79, 0x6d, 0x62, 0x6f, + 0x6c, 0x12, 0x21, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x22, 0x06, 0x0a, 0x04, 0x4e, 0x75, 0x6c, 0x6c, 0x22, 0x1c, 0x0a, 0x04, + 0x42, 0x6f, 0x6f, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1b, 0x0a, 0x03, 0x49, 0x6e, + 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1e, 0x0a, 0x06, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x45, 0x0a, 0x09, 0x43, 0x61, 0x63, 0x68, 0x65, + 0x50, 0x61, 0x74, 0x68, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, + 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x1c, + 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x21, 0x0a, 0x0b, + 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, + 0x1e, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x70, + 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, + 0x1d, 0x0a, 0x07, 0x44, 0x69, 0x72, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, + 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x61, + 0x0a, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, + 0x12, 0x24, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, + 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, + 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x03, 0x64, 0x69, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x44, 0x69, 0x72, 0x50, 0x61, + 0x74, 0x68, 0x48, 0x00, 0x52, 0x03, 0x64, 0x69, 0x72, 0x42, 0x06, 0x0a, 0x04, 0x70, 0x61, 0x74, + 0x68, 0x22, 0x58, 0x0a, 0x09, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x12, 0x21, + 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, + 0x6b, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x4e, 0x0a, 0x08, 0x48, + 0x6f, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0xec, 0x01, 0x0a, 0x0b, + 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x2c, 0x0a, 0x04, 0x66, + 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x61, 0x73, 0x73, + 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x2e, 0x46, 0x69, 0x6c, + 0x65, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x29, 0x0a, 0x03, 0x64, 0x69, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, + 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x2e, 0x44, 0x69, 0x72, 0x48, 0x00, 0x52, + 0x03, 0x64, 0x69, 0x72, 0x1a, 0x34, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x22, 0x21, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x22, 0x1e, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, - 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, - 0x61, 0x74, 0x68, 0x22, 0x1d, 0x0a, 0x07, 0x44, 0x69, 0x72, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x22, 0x61, 0x0a, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, - 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x03, 0x64, 0x69, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x44, - 0x69, 0x72, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x03, 0x64, 0x69, 0x72, 0x42, 0x06, 0x0a, - 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x58, 0x0a, 0x09, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, - 0x74, 0x68, 0x12, 0x21, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x52, 0x05, - 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, - 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, - 0x4e, 0x0a, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, - 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, - 0xec, 0x01, 0x0a, 0x0b, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, - 0x2c, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, - 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, - 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x29, 0x0a, - 0x03, 0x64, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x62, 0x61, 0x73, - 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x2e, 0x44, 0x69, - 0x72, 0x48, 0x00, 0x52, 0x03, 0x64, 0x69, 0x72, 0x1a, 0x34, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x1a, 0x46, - 0x0a, 0x03, 0x44, 0x69, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x07, 0x65, 0x6e, 0x74, - 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x61, 0x73, - 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x52, 0x07, 0x65, - 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x42, 0x0b, - 0x5a, 0x09, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x1a, 0x46, 0x0a, 0x03, 0x44, 0x69, + 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, + 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, + 0x65, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x42, 0x0b, 0x5a, 0x09, 0x70, 0x6b, + 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/proto/runtime.pb.go b/pkg/proto/runtime.pb.go index 5cde192b..2c608f12 100644 --- a/pkg/proto/runtime.pb.go +++ b/pkg/proto/runtime.pb.go @@ -382,26 +382,26 @@ var file_runtime_proto_rawDesc = []byte{ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x22, 0x1b, 0x0a, 0x05, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0xa2, 0x02, 0x0a, 0x07, 0x52, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x12, 0x0e, 0x2e, - 0x62, 0x61, 0x73, 0x73, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, 0x1a, 0x0e, 0x2e, - 0x62, 0x61, 0x73, 0x73, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, 0x22, 0x00, 0x12, - 0x29, 0x0a, 0x03, 0x52, 0x75, 0x6e, 0x12, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, - 0x75, 0x6e, 0x6b, 0x1a, 0x11, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x52, 0x75, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x2b, 0x0a, 0x04, 0x52, 0x65, - 0x61, 0x64, 0x12, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x1a, - 0x12, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x26, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x6f, 0x72, - 0x74, 0x12, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x1a, 0x0b, - 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x00, 0x30, 0x01, 0x12, - 0x3a, 0x0a, 0x07, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x12, 0x14, 0x2e, 0x62, 0x61, 0x73, - 0x73, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x15, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x2e, 0x0a, 0x0a, 0x45, - 0x78, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, - 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x1a, 0x0b, 0x2e, 0x62, 0x61, 0x73, - 0x73, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x00, 0x30, 0x01, 0x42, 0x0b, 0x5a, 0x09, 0x70, - 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0x9f, 0x02, 0x0a, 0x07, 0x52, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x12, 0x0e, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, 0x1a, 0x0b, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x22, 0x00, 0x12, 0x29, 0x0a, 0x03, + 0x52, 0x75, 0x6e, 0x12, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, + 0x1a, 0x11, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x2b, 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64, 0x12, + 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x1a, 0x12, 0x2e, 0x62, + 0x61, 0x73, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x30, 0x01, 0x12, 0x26, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x0b, + 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x1a, 0x0b, 0x2e, 0x62, 0x61, + 0x73, 0x73, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x00, 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x07, + 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x12, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x50, + 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x2e, 0x0a, 0x0a, 0x45, 0x78, 0x70, 0x6f, + 0x72, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, + 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x1a, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x42, + 0x79, 0x74, 0x65, 0x73, 0x22, 0x00, 0x30, 0x01, 0x42, 0x0b, 0x5a, 0x09, 0x70, 0x6b, 0x67, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -441,7 +441,7 @@ var file_runtime_proto_depIdxs = []int32{ 6, // 9: bass.Runtime.Export:input_type -> bass.Thunk 0, // 10: bass.Runtime.Publish:input_type -> bass.PublishRequest 8, // 11: bass.Runtime.ExportPath:input_type -> bass.ThunkPath - 5, // 12: bass.Runtime.Resolve:output_type -> bass.ImageRef + 6, // 12: bass.Runtime.Resolve:output_type -> bass.Thunk 2, // 13: bass.Runtime.Run:output_type -> bass.RunResponse 3, // 14: bass.Runtime.Read:output_type -> bass.ReadResponse 4, // 15: bass.Runtime.Export:output_type -> bass.Bytes diff --git a/pkg/proto/runtime_grpc.pb.go b/pkg/proto/runtime_grpc.pb.go index 1e02a3ce..50b8eda8 100644 --- a/pkg/proto/runtime_grpc.pb.go +++ b/pkg/proto/runtime_grpc.pb.go @@ -31,7 +31,7 @@ const ( // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type RuntimeClient interface { - Resolve(ctx context.Context, in *ImageRef, opts ...grpc.CallOption) (*ImageRef, error) + Resolve(ctx context.Context, in *ImageRef, opts ...grpc.CallOption) (*Thunk, error) Run(ctx context.Context, in *Thunk, opts ...grpc.CallOption) (Runtime_RunClient, error) Read(ctx context.Context, in *Thunk, opts ...grpc.CallOption) (Runtime_ReadClient, error) Export(ctx context.Context, in *Thunk, opts ...grpc.CallOption) (Runtime_ExportClient, error) @@ -47,8 +47,8 @@ func NewRuntimeClient(cc grpc.ClientConnInterface) RuntimeClient { return &runtimeClient{cc} } -func (c *runtimeClient) Resolve(ctx context.Context, in *ImageRef, opts ...grpc.CallOption) (*ImageRef, error) { - out := new(ImageRef) +func (c *runtimeClient) Resolve(ctx context.Context, in *ImageRef, opts ...grpc.CallOption) (*Thunk, error) { + out := new(Thunk) err := c.cc.Invoke(ctx, Runtime_Resolve_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -220,7 +220,7 @@ func (x *runtimeExportPathClient) Recv() (*Bytes, error) { // All implementations must embed UnimplementedRuntimeServer // for forward compatibility type RuntimeServer interface { - Resolve(context.Context, *ImageRef) (*ImageRef, error) + Resolve(context.Context, *ImageRef) (*Thunk, error) Run(*Thunk, Runtime_RunServer) error Read(*Thunk, Runtime_ReadServer) error Export(*Thunk, Runtime_ExportServer) error @@ -233,7 +233,7 @@ type RuntimeServer interface { type UnimplementedRuntimeServer struct { } -func (UnimplementedRuntimeServer) Resolve(context.Context, *ImageRef) (*ImageRef, error) { +func (UnimplementedRuntimeServer) Resolve(context.Context, *ImageRef) (*Thunk, error) { return nil, status.Errorf(codes.Unimplemented, "method Resolve not implemented") } func (UnimplementedRuntimeServer) Run(*Thunk, Runtime_RunServer) error { diff --git a/pkg/runtimes/buildkit.go b/pkg/runtimes/buildkit.go index 40252d66..bd66bcd1 100644 --- a/pkg/runtimes/buildkit.go +++ b/pkg/runtimes/buildkit.go @@ -211,7 +211,7 @@ func dialBuildkit(ctx context.Context, addr string, installation string, certsDi return client, nil } -func (runtime *Buildkit) Resolve(ctx context.Context, imageRef bass.ImageRef) (bass.ImageRef, error) { +func (runtime *Buildkit) Resolve(ctx context.Context, imageRef bass.ImageRef) (bass.Thunk, error) { // track dependent services ctx, svcs := bass.TrackRuns(ctx) defer svcs.StopAndWait() @@ -219,13 +219,13 @@ func (runtime *Buildkit) Resolve(ctx context.Context, imageRef bass.ImageRef) (b ref, err := runtime.ref(ctx, imageRef) if err != nil { // TODO: it might make sense to resolve an OCI archive ref to a digest too - return bass.ImageRef{}, fmt.Errorf("resolve ref %v: %w", imageRef, err) + return bass.Thunk{}, fmt.Errorf("resolve ref %v: %w", imageRef, err) } // convert 'ubuntu' to 'docker.io/library/ubuntu:latest' normalized, err := reference.ParseNormalizedNamed(ref) if err != nil { - return bass.ImageRef{}, fmt.Errorf("normalize ref: %w", err) + return bass.Thunk{}, fmt.Errorf("normalize ref: %w", err) } statusProxy := forwardStatus(progrock.RecorderFromContext(ctx)) @@ -250,10 +250,10 @@ func (runtime *Buildkit) Resolve(ctx context.Context, imageRef bass.ImageRef) (b }, }, buildkitProduct, doBuild, statusProxy.Writer()) if err != nil { - return bass.ImageRef{}, statusProxy.NiceError("resolve failed", err) + return bass.Thunk{}, statusProxy.NiceError("resolve failed", err) } - return imageRef, nil + return imageRef.Thunk(), nil } func (runtime *Buildkit) Run(ctx context.Context, thunk bass.Thunk) error { @@ -265,7 +265,8 @@ func (runtime *Buildkit) Run(ctx context.Context, thunk bass.Thunk) error { func(st llb.ExecState, _ string) llb.State { return st.GetMount(ioDir) }, - nil, // exports + nil, // exports + true, // inherit entrypoint/cmd ) return err } @@ -293,7 +294,8 @@ func (runtime *Buildkit) Start(ctx context.Context, thunk bass.Thunk) (StartResu func(st llb.ExecState, _ string) llb.State { return st.GetMount(ioDir) }, - nil, // exports + nil, // exports + true, // inherit entrypoint/cmd ) exited <- err @@ -354,6 +356,7 @@ func (runtime *Buildkit) Read(ctx context.Context, w io.Writer, thunk bass.Thunk OutputDir: tmp, }, }, + true, // inherit entrypoint/cmd llb.AddEnv("_BASS_OUTPUT", outputFile), ) if err != nil { @@ -394,6 +397,7 @@ func (runtime *Buildkit) Export(ctx context.Context, w io.Writer, thunk bass.Thu }, }, }, + false, // do not inherit entrypoint/cmd ) return err } @@ -422,6 +426,7 @@ func (runtime *Buildkit) Publish(ctx context.Context, ref bass.ImageRef, thunk b }, }, }, + false, // do not inherit entrypoint/cmd ) if err != nil { return ref, err @@ -464,6 +469,7 @@ func (runtime *Buildkit) ExportPath(ctx context.Context, w io.Writer, tp bass.Th }, }, }, + true, // inherit entryopint/cmd ) return err } @@ -524,6 +530,7 @@ func (runtime *Buildkit) build( thunk bass.Thunk, transform func(llb.ExecState, string) llb.State, exports []kitdclient.ExportEntry, + forceExec bool, runOpts ...llb.RunOption, ) (*kitdclient.SolveResponse, error) { var def *llb.Definition @@ -541,7 +548,7 @@ func (runtime *Buildkit) build( }, buildkitProduct, func(ctx context.Context, gw gwclient.Client) (*gwclient.Result, error) { b := runtime.newBuilder(ctx, gw) - ib, err := b.llb(ctx, thunk, transform, runOpts...) + ib, err := b.llb(ctx, thunk, transform, forceExec, runOpts...) if err != nil { return nil, err } @@ -743,6 +750,7 @@ func (b *buildkitBuilder) llb( ctx context.Context, thunk bass.Thunk, transform func(llb.ExecState, string) llb.State, + forceExec bool, extraOpts ...llb.RunOption, ) (intermediateBuild, error) { ib, err := b.image(ctx, thunk.Image) @@ -761,12 +769,12 @@ func (b *buildkitBuilder) llb( } // propagate thunk's entrypoint to the child - if thunk.Entrypoint != nil { // note: nil vs. [] distinction + if len(thunk.Entrypoint) > 0 || thunk.ClearEntrypoint { ib.config.Entrypoint = thunk.Entrypoint } // propagate thunk's default command - if thunk.DefaultArgs != nil { // note: nil vs. [] distinction + if len(thunk.DefaultArgs) > 0 || thunk.ClearDefaultArgs { ib.config.Cmd = thunk.DefaultArgs } @@ -786,9 +794,22 @@ func (b *buildkitBuilder) llb( } } - if cmd.Args == nil { // note: nil vs. [] distinction - // no command; we're just overriding config - return ib, nil + if len(thunk.Ports) > 0 { + if ib.config.ExposedPorts == nil { + ib.config.ExposedPorts = map[string]struct{}{} + } + for _, port := range thunk.Ports { + ib.config.ExposedPorts[fmt.Sprintf("%d/tcp", port.Port)] = struct{}{} + } + } + + if len(cmd.Args) == 0 { + if forceExec { + cmd.Args = append(ib.config.Entrypoint, ib.config.Cmd...) + } else { + // no command; we're just overriding config + return ib, nil + } } cmdPayload, err := bass.MarshalJSON(cmd) @@ -1047,7 +1068,7 @@ func (b *buildkitBuilder) image(ctx context.Context, image *bass.ThunkImage) (ib return ib, nil case image.Thunk != nil: - return b.llb(ctx, *image.Thunk, getWorkdir) + return b.llb(ctx, *image.Thunk, getWorkdir, false) case image.Archive != nil: file, err := image.Archive.File.Open(ctx) @@ -1155,7 +1176,7 @@ func (b *buildkitBuilder) image(ctx context.Context, image *bass.ThunkImage) (ib const defaultDockerfileName = "Dockerfile" - if dockerfile.Path != "" { + if dockerfile != nil { opts["filename"] = path.Join(sourcePath, dockerfile.Slash()) } else { opts["filename"] = path.Join(sourcePath, defaultDockerfileName) @@ -1329,7 +1350,7 @@ func (b *buildkitBuilder) initializeMount(ctx context.Context, source bass.Thunk } func (b *buildkitBuilder) thunkPathSt(ctx context.Context, source bass.ThunkPath) (llb.State, string, bool, error) { - ib, err := b.llb(ctx, source.Thunk, getWorkdir) + ib, err := b.llb(ctx, source.Thunk, getWorkdir, true) if err != nil { return llb.State{}, "", false, fmt.Errorf("thunk llb: %w", err) } diff --git a/pkg/runtimes/dagger.go b/pkg/runtimes/dagger.go index 68db78d1..49d376eb 100644 --- a/pkg/runtimes/dagger.go +++ b/pkg/runtimes/dagger.go @@ -57,13 +57,13 @@ func NewDagger(ctx context.Context, _ bass.RuntimePool, cfg *bass.Scope) (bass.R }, nil } -func (runtime *Dagger) Resolve(ctx context.Context, imageRef bass.ImageRef) (bass.ImageRef, error) { +func (runtime *Dagger) Resolve(ctx context.Context, imageRef bass.ImageRef) (bass.Thunk, error) { // TODO - return imageRef, nil + return imageRef.Thunk(), nil } func (runtime *Dagger) Run(ctx context.Context, thunk bass.Thunk) error { - ctr, err := runtime.container(ctx, thunk) + ctr, err := runtime.container(ctx, thunk, true) if err != nil { return err } @@ -97,7 +97,7 @@ func (runtime *Dagger) Start(ctx context.Context, thunk bass.Thunk) (StartResult } func (runtime *Dagger) Read(ctx context.Context, w io.Writer, thunk bass.Thunk) error { - ctr, err := runtime.container(ctx, thunk) + ctr, err := runtime.container(ctx, thunk, true) if err != nil { return err } @@ -116,7 +116,7 @@ func (runtime *Dagger) Read(ctx context.Context, w io.Writer, thunk bass.Thunk) } func (runtime *Dagger) Publish(ctx context.Context, ref bass.ImageRef, thunk bass.Thunk) (bass.ImageRef, error) { - ctr, err := runtime.container(ctx, thunk) + ctr, err := runtime.container(ctx, thunk, false) if err != nil { return ref, err } @@ -147,7 +147,7 @@ func (runtime *Dagger) Publish(ctx context.Context, ref bass.ImageRef, thunk bas } func (runtime *Dagger) Export(ctx context.Context, w io.Writer, thunk bass.Thunk) error { - ctr, err := runtime.container(ctx, thunk) + ctr, err := runtime.container(ctx, thunk, false) if err != nil { return err } @@ -188,7 +188,7 @@ func (runtime *Dagger) ExportPath(ctx context.Context, w io.Writer, tp bass.Thun defer os.RemoveAll(dir) - ctr, err := runtime.container(ctx, tp.Thunk) + ctr, err := runtime.container(ctx, tp.Thunk, true) if err != nil { return err } @@ -220,7 +220,7 @@ func (runtime *Dagger) Close() error { return runtime.client.Close() } -func (runtime *Dagger) container(ctx context.Context, thunk bass.Thunk) (*dagger.Container, error) { +func (runtime *Dagger) container(ctx context.Context, thunk bass.Thunk, forceExec bool) (*dagger.Container, error) { cmd, err := NewCommand(ctx, runtime, thunk) if err != nil { return nil, err @@ -276,7 +276,7 @@ func (runtime *Dagger) container(ctx context.Context, thunk bass.Thunk) (*dagger // TODO: TLS for _, svc := range cmd.Services { - svcCtr, err := runtime.container(ctx, svc) + svcCtr, err := runtime.container(ctx, svc, true) if err != nil { return nil, err } @@ -324,13 +324,6 @@ func (runtime *Dagger) container(ctx context.Context, thunk bass.Thunk) (*dagger return nil, err } - // Don't respect the entrypoint; this is way too confusing: - // - // (from (linux/alpine/git) - // ($ clone "https://github.com/vito/bass")) - // - // Bass thunks feel are similar to Dockerfiles, which also don't respect - // entrypoints. if len(ep) > 0 { ctr = ctr.WithEntrypoint(nil) } @@ -340,10 +333,11 @@ func (runtime *Dagger) container(ctx context.Context, thunk bass.Thunk) (*dagger InsecureRootCapabilities: thunk.Insecure, }) - // Restore the entrypoint so it's still around when publishing. if len(ep) > 0 { ctr = ctr.WithEntrypoint(ep) } + } else if forceExec { + ctr = ctr.WithExec(nil) } if thunk.Entrypoint != nil { @@ -368,7 +362,7 @@ func (runtime *Dagger) mount(ctx context.Context, ctr *dagger.Container, target switch { case src.ThunkPath != nil: - srcCtr, err := runtime.container(ctx, src.ThunkPath.Thunk) + srcCtr, err := runtime.container(ctx, src.ThunkPath.Thunk, true) if err != nil { return nil, err } @@ -462,7 +456,7 @@ func (runtime *Dagger) image(ctx context.Context, image *bass.ThunkImage) (strin } if image.Thunk != nil { - ctr, err := runtime.container(ctx, *image.Thunk) + ctr, err := runtime.container(ctx, *image.Thunk, false) if err != nil { return "", nil, fmt.Errorf("image thunk llb: %w", err) } diff --git a/pkg/runtimes/dagger_test.go b/pkg/runtimes/dagger_test.go index da8f9d35..2e78e994 100644 --- a/pkg/runtimes/dagger_test.go +++ b/pkg/runtimes/dagger_test.go @@ -22,5 +22,12 @@ func TestDaggerRuntime(t *testing.T) { runtimes.Suite(t, bass.RuntimeConfig{ Platform: bass.LinuxPlatform, Runtime: runtimes.DaggerName, - }) + }, runtimes.SkipSuites( + "tls.bass", + "addrs.bass", + "docker-build.bass", + "cache-cmd.bass", + "oci-archive-image.bass", + // secrets don't get sent over gRPC + )) } diff --git a/pkg/runtimes/grpc.go b/pkg/runtimes/grpc.go index 3b4c1232..b7f57b48 100644 --- a/pkg/runtimes/grpc.go +++ b/pkg/runtimes/grpc.go @@ -53,21 +53,20 @@ func NewClient(ctx context.Context, _ bass.RuntimePool, cfg *bass.Scope) (bass.R }, nil } -func (client *Client) Resolve(ctx context.Context, ref bass.ImageRef) (bass.ImageRef, error) { - ret := bass.ImageRef{} - +func (client *Client) Resolve(ctx context.Context, ref bass.ImageRef) (bass.Thunk, error) { p, err := ref.MarshalProto() if err != nil { - return ret, err + return bass.Thunk{}, err } r, err := client.RuntimeClient.Resolve(ctx, p.(*proto.ImageRef)) if err != nil { - return ret, err + return bass.Thunk{}, err } + ret := bass.Thunk{} if err := ret.UnmarshalProto(r); err != nil { - return ret, err + return bass.Thunk{}, err } return ret, nil @@ -275,7 +274,7 @@ type Server struct { proto.UnimplementedRuntimeServer } -func (srv *Server) Resolve(_ context.Context, p *proto.ImageRef) (*proto.ImageRef, error) { +func (srv *Server) Resolve(_ context.Context, p *proto.ImageRef) (*proto.Thunk, error) { ref := bass.ImageRef{} err := ref.UnmarshalProto(p) @@ -293,7 +292,7 @@ func (srv *Server) Resolve(_ context.Context, p *proto.ImageRef) (*proto.ImageRe return nil, err } - return ret.(*proto.ImageRef), err + return ret.(*proto.Thunk), err } func (srv *Server) Run(p *proto.Thunk, runSrv proto.Runtime_RunServer) error { diff --git a/pkg/runtimes/suite.go b/pkg/runtimes/suite.go index 9e662432..355a684a 100644 --- a/pkg/runtimes/suite.go +++ b/pkg/runtimes/suite.go @@ -210,8 +210,7 @@ func Suite(t *testing.T, runtimeConfig bass.RuntimeConfig, opts ...SuiteOpt) { ), }, { - File: "oci-archive-image.bass", - Result: bass.String("/go"), + File: "oci-archive-image.bass", }, { File: "remount-workdir.bass", @@ -238,12 +237,10 @@ func Suite(t *testing.T, runtimeConfig bass.RuntimeConfig, opts ...SuiteOpt) { Result: bass.String("hello, world!\n"), }, { - File: "addrs.bass", - Result: bass.String("hello, world!"), + File: "addrs.bass", }, { - File: "tls.bass", - Result: bass.Bool(true), + File: "tls.bass", }, { File: "secrets.bass", @@ -294,17 +291,9 @@ func Suite(t *testing.T, runtimeConfig bass.RuntimeConfig, opts ...SuiteOpt) { // TODO: test publishing somehow :/ { File: "docker-build.bass", - Result: bass.NewList( - bass.String("hello from Dockerfile\n"), - bass.String("hello from Dockerfile.alt\n"), - bass.String("hello from alt stage in Dockerfile\n"), - bass.String("hello from Dockerfile with message sup\n"), - bass.String("hello from Dockerfile with env bar\nbar\n"), - ), }, { - File: "entrypoints.bass", - Result: bass.Null{}, + File: "entrypoints.bass", }, } { test := test @@ -405,7 +394,9 @@ func (test SuiteTest) Run(ctx context.Context, t *testing.T, env *bass.Scope) (v Stdin: bass.NewSource(bass.NewInMemorySource()), Stdout: bass.NewSink(bass.NewJSONSink("stdout", vtx.Stdout())), }) - scope.Set("*memos*", bass.NewHostPath("./testdata/", bass.ParseFileOrDirPath("bass.lock"))) + + // NB: coupled to repo organization + scope.Set("*memos*", bass.NewHostPath("../../bass/", bass.ParseFileOrDirPath("bass.lock"))) scope.Set("*display*", bass.Func("*display*", "[]", func() string { return displayBuf.String() })) diff --git a/pkg/runtimes/testdata/addrs.bass b/pkg/runtimes/testdata/addrs.bass index ee41fbb6..0858de6e 100644 --- a/pkg/runtimes/testdata/addrs.bass +++ b/pkg/runtimes/testdata/addrs.bass @@ -1,12 +1,34 @@ +(use (*dir*/lib/oci.bass)) + (defn http-server [index] (from (linux/busybox) (-> ($ httpd -f -p "8000") (with-mount (mkfile ./index.html index) ./index.html) (with-port :http 8000)))) -(let [srv (http-server "hello, world!")] - (-> ($ wget -O- (addr srv :http "http://$host:$port")) - (with-image (linux/busybox)) - (read :raw) - next - dump)) +(assert = "hello, world!" + (let [srv (http-server "hello, world!")] + (-> ($ wget -O- (addr srv :http "http://$host:$port")) + (with-image (linux/busybox)) + (read :raw) + next))) + +(defn entrypoint-server [index] + (-> (linux/busybox) + (with-entrypoint ["httpd" "-f" "-p" "8000"]) + (with-mount (mkfile ./index.html index) ./index.html) + (with-port :http 8000))) + +(assert = "hello, world!" + (let [srv (entrypoint-server "hello, world!")] + (-> ($ wget -O- (addr srv :http "http://$host:$port")) + (with-image (linux/busybox)) + (read :raw) + next))) + +(defn exposed-ports [thunk] + (let [config (oci:config thunk)] + (:ExposedPorts config null))) + +(assert = {(string->symbol "8000/tcp") {}} + (exposed-ports (entrypoint-server "hello, world!"))) diff --git a/pkg/runtimes/testdata/bass.lock b/pkg/runtimes/testdata/bass.lock index fa67c2fe..5fc0e374 100644 --- a/pkg/runtimes/testdata/bass.lock +++ b/pkg/runtimes/testdata/bass.lock @@ -8,90 +8,6 @@ memos: { } calls: { binding: "resolve" - results: { - input: { - array: { - values: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine/git" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "2.36.3" - } - } - } - } - } - } - } - output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine/git" - } - } - } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "architecture" - value: { - string: { - value: "amd64" - } - } - } - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "2.36.3" - } - } - } - } - } - } results: { input: { array: { @@ -133,44 +49,16 @@ memos: { } } output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine" - } - } - } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "architecture" - value: { - string: { - value: "amd64" - } - } - } - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "alpine" + tag: "latest" + digest: "sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126" } } } diff --git a/pkg/runtimes/testdata/docker-build.bass b/pkg/runtimes/testdata/docker-build.bass index be3cdcc4..4e4bfa89 100644 --- a/pkg/runtimes/testdata/docker-build.bass +++ b/pkg/runtimes/testdata/docker-build.bass @@ -1,17 +1,33 @@ -(map (fn [thunk] (next (read thunk :raw))) - [(from (docker-build *dir*/docker-build/ {:os "linux"}) - ($ cat ./wd-file)) - (from (docker-build *dir*/docker-build/ {:os "linux"} - :dockerfile ./Dockerfile.alt) - ($ cat ./wd-file)) - (from (docker-build *dir*/docker-build/ {:os "linux"} - :target "alt") - ($ cat ./wd-file)) - (from (docker-build *dir*/docker-build/ {:os "linux"} - :target "arg" - :args {:MESSAGE "sup"}) - ($ cat ./wd-file)) - (from (docker-build *dir*/docker-build/ {:os "linux"} - :target "env") - ($ sh -c "cat ./wd-file; echo $FOO")) - ]) +(defn out [thunk] + (-> thunk (read :raw) next)) + +(assert = "hello from Dockerfile\n" + (out + (from (docker-build *dir*/docker-build/ {:os "linux"}) + ($ cat ./wd-file)))) + +(assert = "hello from Dockerfile.alt\n" + (out + (from (docker-build *dir*/docker-build/ {:os "linux"} + :dockerfile ./Dockerfile.alt) + ($ cat ./wd-file)))) + + +(assert = "hello from alt stage in Dockerfile\n" + (out + (from (docker-build *dir*/docker-build/ {:os "linux"} + :target "alt") + ($ cat ./wd-file)))) + +(assert = "hello from Dockerfile with message sup\n" + (out + (from (docker-build *dir*/docker-build/ {:os "linux"} + :target "arg" + :args {:MESSAGE "sup"}) + ($ cat ./wd-file)))) + +(assert = "hello from Dockerfile with env bar\nbar\n" + (out + (from (docker-build *dir*/docker-build/ {:os "linux"} + :target "env") + ($ sh -c "cat ./wd-file; echo $FOO")))) diff --git a/pkg/runtimes/testdata/entrypoints.bass b/pkg/runtimes/testdata/entrypoints.bass index 03fe2d44..f8a6079c 100644 --- a/pkg/runtimes/testdata/entrypoints.bass +++ b/pkg/runtimes/testdata/entrypoints.bass @@ -1,51 +1,52 @@ -(defn tar-file [tar path] - (defn find-file [stream] - (let [file (next stream) - info (meta file) - name (path-name file)] - (if (= name path) - file - (find-file stream)))) - - (find-file (read tar :tar))) +(use (.strings) + (*dir*/lib/oci.bass)) (defn entrypoint [thunk] - (let [config-path (-> (tar-file (export thunk) "manifest.json") - (read :json) - next - first ; contains array of manifests - :Config - string->fs-path) - config (-> (tar-file (export thunk) (path-name config-path)) - (read :json) - next - :config)] + (let [config (oci:config thunk)] (:Entrypoint config null))) -(def from-image +(def not-respected (from (linux/alpine/git :2.36.3) ($ git --version))) -(assert = "git version 2.36.3" (-> from-image (read :lines) next)) -(assert = ["git"] (entrypoint from-image)) +; entrypoint is *not* respected by ($) +(assert = "git version 2.36.3\n" + (-> not-respected + (read :raw) + next)) + +; but it is preserved +(assert = ["git"] + (entrypoint not-respected)) + +; entrypoint *is* respected when running directly +(assert strings:includes? + (-> (linux/hello-world) + (read :raw) + next) + "Hello from Docker") (def unset-image - (from (linux/alpine/git :2.36.3) - (with-entrypoint ($) []) - ($ git --version))) + (-> (linux/alpine/git :2.36.3) + (with-entrypoint []))) -(assert = "git version 2.36.3" - (-> unset-image (read :lines) next)) -(assert null? (entrypoint unset-image)) +; ; entrypoint is removed when set to empty list +(assert null? + (entrypoint unset-image)) (def set-thunk - (from (linux/alpine) - (with-entrypoint ($) ["sh"]))) + (-> (from (linux/busybox) + ($ touch index.html)) + (with-entrypoint ["httpd" "-f" "-p" "8000"]))) -(assert = ["sh"] (entrypoint set-thunk)) +; entrypoint can be set by thunk +(assert = ["httpd" "-f" "-p" "8000"] + (entrypoint set-thunk)) (def keeps-entrypoint (from set-thunk ($ echo "Hello, world!"))) -(assert = ["sh"] (entrypoint keeps-entrypoint)) +; entrypoint is preserved from thunk to thunk +(assert = ["httpd" "-f" "-p" "8000"] + (entrypoint keeps-entrypoint)) diff --git a/pkg/runtimes/testdata/lib/oci.bass b/pkg/runtimes/testdata/lib/oci.bass new file mode 100644 index 00000000..c8529097 --- /dev/null +++ b/pkg/runtimes/testdata/lib/oci.bass @@ -0,0 +1,25 @@ +(provide [config] + (defn config [thunk] + (let [config-path (-> (tar-file (export thunk) "manifest.json") + (read :json) + next + first ; contains array of manifests + :Config + string->fs-path) + config (-> (tar-file (export thunk) (path-name config-path)) + (read :json) + next + :config)] + config)) + + (defn tar-file [tar path] + (defn find-file [stream] + (let [file (next stream) + info (meta file) + name (path-name file)] + (if (= name path) + file + (find-file stream)))) + (find-file (read tar :tar))) + +) diff --git a/pkg/runtimes/testdata/oci-archive-image.bass b/pkg/runtimes/testdata/oci-archive-image.bass index 03fb44dd..008ff78a 100644 --- a/pkg/runtimes/testdata/oci-archive-image.bass +++ b/pkg/runtimes/testdata/oci-archive-image.bass @@ -8,11 +8,14 @@ ./image.tar)) (def go-image - {:file go-archive - :platform {:os "linux"} - :tag "latest"}) + (oci-load go-archive {:os "linux"} :tag "latest")) + +(run (from go-image + ($ go env GOPATH))) ; test that both $PATH and $GOPATH from image config are respected -(-> (from go-image ($ go env GOPATH)) - (read :lines) - next) +(assert = "/go" + (-> (from go-image + ($ go env GOPATH)) + (read :lines) + next)) diff --git a/pkg/runtimes/testdata/tls.bass b/pkg/runtimes/testdata/tls.bass index cc5187b5..634b7b4f 100644 --- a/pkg/runtimes/testdata/tls.bass +++ b/pkg/runtimes/testdata/tls.bass @@ -28,5 +28,5 @@ (addr mirror :http "https://$host:$port/v2/library/alpine/manifests/latest")))) -(= (-> manifest (read :json) next :tag) - "latest") +(assert = "latest" + (-> manifest (read :json) next :tag)) diff --git a/proto/bass.proto b/proto/bass.proto index 618b3465..e163ee60 100644 --- a/proto/bass.proto +++ b/proto/bass.proto @@ -35,6 +35,10 @@ message Thunk { repeated Binding labels = 9; repeated ThunkPort ports = 10; ThunkTLS tls = 11; + repeated string entrypoint = 12; + bool clear_entrypoint = 13; + repeated string default_args = 14; + bool clear_default_args = 15; }; message ThunkAddr { diff --git a/proto/runtime.proto b/proto/runtime.proto index 463afda6..5ecfee22 100644 --- a/proto/runtime.proto +++ b/proto/runtime.proto @@ -7,7 +7,7 @@ import "progress.proto"; import "bass.proto"; service Runtime { - rpc Resolve(ImageRef) returns (ImageRef) {} + rpc Resolve(ImageRef) returns (Thunk) {} rpc Run(Thunk) returns (stream RunResponse) {} rpc Read(Thunk) returns (stream ReadResponse) {} rpc Export(Thunk) returns (stream Bytes) {} diff --git a/std/run.bass b/std/run.bass index 8c230463..c07acc18 100644 --- a/std/run.bass +++ b/std/run.bass @@ -132,8 +132,7 @@ (let [path-root (path {:os "linux"} (:*memos* scope null))] (eval [path-root & args] scope)))) -; returns an image that will be built from a Dockerfile in the context -; directory +; returns a thunk built from a Dockerfile in the context directory ; ; Additional parameters may be passed as opts: ; @@ -151,7 +150,24 @@ ; ; => (docker-build *dir* {:os "linux"} :args {:FOO "bar"}) (defn docker-build [context platform & opts] - (merge - {:platform platform - :docker_build context} - (list->scope opts))) + (from (merge + {:platform platform + :docker_build context} + (list->scope opts)) + scratch)) + +; returns a thunk loaded from an OCI image tarball +; +; Additional parameters may be passed as opts: +; +; :tag specifies a tag to load. +; +; => (def build ($ nix build .)) +; +; => (oci-load build/result {:os "linux"}) +(defn oci-load [file platform & opts] + (from (merge + {:platform platform + :file file} + (list->scope opts)) + scratch)) From 54a78f557343594babbeb022f61a6f8a3368d83c Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Sat, 8 Apr 2023 22:23:33 -0400 Subject: [PATCH 13/16] fix more entrypoint situations this was hard to figure out, but it works, and should be close to what Dagger does. there is probably be a better way to model this, but I think it achieves the desired semantics. --- pkg/bass/thunk.go | 35 ++++++++++++++++++---- pkg/runtimes/buildkit.go | 3 ++ pkg/runtimes/dagger.go | 8 +++--- pkg/runtimes/grpc_test.go | 1 + pkg/runtimes/testdata/entrypoints.bass | 40 ++++++++++++++++++++------ 5 files changed, 69 insertions(+), 18 deletions(-) diff --git a/pkg/bass/thunk.go b/pkg/bass/thunk.go index de0d258c..d2a4daef 100644 --- a/pkg/bass/thunk.go +++ b/pkg/bass/thunk.go @@ -443,22 +443,45 @@ func (thunk Thunk) WithImage(image ThunkImage) Thunk { // WithEntrypoint sets the thunk's entrypoint. func (thunk Thunk) WithEntrypoint(entrypoint []string) Thunk { - if len(entrypoint) == 0 { - thunk.ClearEntrypoint = true - } + thunk = thunk.encapsulate() thunk.Entrypoint = entrypoint + thunk.ClearEntrypoint = len(entrypoint) == 0 return thunk } // WithDefaultArgs sets the thunk's default arguments. func (thunk Thunk) WithDefaultArgs(args []string) Thunk { - if len(args) == 0 { - thunk.ClearDefaultArgs = true - } + thunk = thunk.encapsulate() thunk.DefaultArgs = args + thunk.ClearDefaultArgs = len(args) == 0 return thunk } +// encapsulate is used to transition from a "build-time" thunk to a "run-time" +// thunk by configuring an entrypoint and/or default args. It returns a thunk +// with no args and an image that points to the original thunk. The returned +// thunk also inherits the original thunk's ports, labels, and workdir. +func (thunk Thunk) encapsulate() Thunk { + if len(thunk.Args) == 0 { + // already encapsulated + return thunk + } else { + return Thunk{ + Image: &ThunkImage{ + Thunk: &thunk, + }, + // no args + Dir: thunk.Dir, + Ports: thunk.Ports, + Labels: thunk.Labels, + Entrypoint: thunk.Entrypoint, + ClearEntrypoint: thunk.ClearEntrypoint, + DefaultArgs: thunk.DefaultArgs, + ClearDefaultArgs: thunk.ClearDefaultArgs, + } + } +} + // WithArgs sets the thunk's arg values. func (thunk Thunk) WithArgs(args []Value) Thunk { thunk.Args = args diff --git a/pkg/runtimes/buildkit.go b/pkg/runtimes/buildkit.go index bd66bcd1..8eebd823 100644 --- a/pkg/runtimes/buildkit.go +++ b/pkg/runtimes/buildkit.go @@ -806,6 +806,9 @@ func (b *buildkitBuilder) llb( if len(cmd.Args) == 0 { if forceExec { cmd.Args = append(ib.config.Entrypoint, ib.config.Cmd...) + if len(cmd.Args) == 0 { + return ib, fmt.Errorf("no command specified") + } } else { // no command; we're just overriding config return ib, nil diff --git a/pkg/runtimes/dagger.go b/pkg/runtimes/dagger.go index 49d376eb..98d54dc5 100644 --- a/pkg/runtimes/dagger.go +++ b/pkg/runtimes/dagger.go @@ -318,7 +318,7 @@ func (runtime *Dagger) container(ctx context.Context, thunk bass.Thunk, forceExe ctr = ctr.WithSecretVariable(env.Name, secret) } - if cmd.Args != nil { + if len(cmd.Args) > 0 { ep, err := ctr.Entrypoint(ctx) if err != nil { return nil, err @@ -337,14 +337,14 @@ func (runtime *Dagger) container(ctx context.Context, thunk bass.Thunk, forceExe ctr = ctr.WithEntrypoint(ep) } } else if forceExec { - ctr = ctr.WithExec(nil) + ctr = ctr.WithExec(append(thunk.Entrypoint, thunk.DefaultArgs...)) } - if thunk.Entrypoint != nil { + if len(thunk.Entrypoint) > 0 || thunk.ClearEntrypoint { ctr = ctr.WithEntrypoint(thunk.Entrypoint) } - if thunk.DefaultArgs != nil { + if len(thunk.DefaultArgs) > 0 || thunk.ClearDefaultArgs { ctr = ctr.WithDefaultArgs(dagger.ContainerWithDefaultArgsOpts{ Args: thunk.DefaultArgs, }) diff --git a/pkg/runtimes/grpc_test.go b/pkg/runtimes/grpc_test.go index a34bbec4..cd2e803c 100644 --- a/pkg/runtimes/grpc_test.go +++ b/pkg/runtimes/grpc_test.go @@ -48,6 +48,7 @@ func TestGRPCRuntime(t *testing.T) { { Platform: bass.LinuxPlatform, Runtime: runtimes.BuildkitName, + Config: config.Scope(), }, }, }) diff --git a/pkg/runtimes/testdata/entrypoints.bass b/pkg/runtimes/testdata/entrypoints.bass index f8a6079c..715544bf 100644 --- a/pkg/runtimes/testdata/entrypoints.bass +++ b/pkg/runtimes/testdata/entrypoints.bass @@ -15,38 +15,62 @@ (read :raw) next)) -; but it is preserved +; but it is preserved in the published image (assert = ["git"] (entrypoint not-respected)) ; entrypoint *is* respected when running directly +(run (linux/hello-world)) + +; or reading (assert strings:includes? (-> (linux/hello-world) (read :raw) next) "Hello from Docker") +; or accessing a path +(def create-path + (-> (linux/alpine) + (with-entrypoint ["sh" "-c" "echo hello > index.html"]))) + +(assert = "hello\n" + (-> create-path/index.html + (read :raw) + next)) + +; entrypoint is removed when set to empty list (def unset-image (-> (linux/alpine/git :2.36.3) (with-entrypoint []))) -; ; entrypoint is removed when set to empty list (assert null? (entrypoint unset-image)) -(def set-thunk +; entrypoint can be set by thunk +(def touch-and-run (-> (from (linux/busybox) - ($ touch index.html)) + ($ sh -c "echo hello from index.html > index.html")) + (with-port :http 8000) (with-entrypoint ["httpd" "-f" "-p" "8000"]))) -; entrypoint can be set by thunk (assert = ["httpd" "-f" "-p" "8000"] - (entrypoint set-thunk)) + (entrypoint touch-and-run)) +; entrypoint is preserved from thunk to thunk (def keeps-entrypoint - (from set-thunk + (from touch-and-run ($ echo "Hello, world!"))) -; entrypoint is preserved from thunk to thunk (assert = ["httpd" "-f" "-p" "8000"] (entrypoint keeps-entrypoint)) + +; entrypoint is respected after running a command +(def wget + (from (linux/alpine) + ($ wget -O- (addr touch-and-run :http "http://$host:$port/")))) + +(assert = "hello from index.html\n" + (-> wget + (read :raw) + next)) From e829c37a66838e972c872fe4ebbd2f7fa40b40f3 Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Sun, 9 Apr 2023 01:52:49 -0400 Subject: [PATCH 14/16] pin bass-loop --- bass/bass.lock | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/bass/bass.lock b/bass/bass.lock index da6fb176..852c360b 100644 --- a/bass/bass.lock +++ b/bass/bass.lock @@ -504,5 +504,26 @@ memos: { } } } + results: { + input: { + array: { + values: { + string: { + value: "https://github.com/vito/bass-loop" + } + } + values: { + string: { + value: "main" + } + } + } + } + output: { + string: { + value: "0fd154b53db44c0dced9b61092db79953d69bd13" + } + } + } } } From cbf7992e108429fbd6f9d22193f8224089d63cf4 Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Sun, 9 Apr 2023 12:32:25 -0400 Subject: [PATCH 15/16] consolidate test bass.locks --- pkg/runtimes/testdata/bass.lock | 68 ------------------- pkg/runtimes/testdata/cache-cmd.bass | 2 - pkg/runtimes/testdata/cache-paths.bass | 2 - pkg/runtimes/testdata/cache-sync.bass | 2 - pkg/runtimes/testdata/dir.bass | 2 - pkg/runtimes/testdata/env.bass | 2 - pkg/runtimes/testdata/fs-paths.bass | 2 - pkg/runtimes/testdata/host-paths-sparse.bass | 2 - pkg/runtimes/testdata/host-paths.bass | 2 - .../testdata/many-layers-workdir.bass | 2 - pkg/runtimes/testdata/mount-run-dir.bass | 2 - pkg/runtimes/testdata/mount.bass | 2 - pkg/runtimes/testdata/multi-env.bass | 2 - pkg/runtimes/testdata/oci-archive-image.bass | 2 - pkg/runtimes/testdata/read-path.bass | 2 - pkg/runtimes/testdata/recursive.bass | 2 - .../testdata/remount-workdir-subdir.bass | 2 - pkg/runtimes/testdata/remount-workdir.bass | 2 - pkg/runtimes/testdata/response-file.bass | 2 - pkg/runtimes/testdata/response-stdout.bass | 2 - pkg/runtimes/testdata/run-thunk-path.bass | 2 - pkg/runtimes/testdata/secrets.bass | 2 - pkg/runtimes/testdata/sleep.bass | 2 - pkg/runtimes/testdata/succeeds.bass | 2 - .../thunk-path-dir-thunk-path-inputs.bass | 2 - pkg/runtimes/testdata/thunk-path-dir.bass | 2 - pkg/runtimes/testdata/thunk-path-env.bass | 2 - pkg/runtimes/testdata/thunk-path-image.bass | 2 - pkg/runtimes/testdata/thunk-paths.bass | 2 - pkg/runtimes/testdata/timestamps.bass | 2 - 30 files changed, 126 deletions(-) delete mode 100644 pkg/runtimes/testdata/bass.lock diff --git a/pkg/runtimes/testdata/bass.lock b/pkg/runtimes/testdata/bass.lock deleted file mode 100644 index 5fc0e374..00000000 --- a/pkg/runtimes/testdata/bass.lock +++ /dev/null @@ -1,68 +0,0 @@ -memos: { - module: { - args: { - command_path: { - name: "run" - } - } - } - calls: { - binding: "resolve" - results: { - input: { - array: { - values: { - object: { - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" - } - } - } - } - } - } - bindings: { - symbol: "repository" - value: { - string: { - value: "alpine" - } - } - } - bindings: { - symbol: "tag" - value: { - string: { - value: "latest" - } - } - } - } - } - } - } - output: { - thunk: { - image: { - ref: { - platform: { - os: "linux" - arch: "amd64" - } - repository: "alpine" - tag: "latest" - digest: "sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126" - } - } - } - } - } - } -} diff --git a/pkg/runtimes/testdata/cache-cmd.bass b/pkg/runtimes/testdata/cache-cmd.bass index dc8c9007..1a9ff0b4 100644 --- a/pkg/runtimes/testdata/cache-cmd.bass +++ b/pkg/runtimes/testdata/cache-cmd.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def test-cache-path (cache-dir (str "test-cache-cmd-" (now 0)))) diff --git a/pkg/runtimes/testdata/cache-paths.bass b/pkg/runtimes/testdata/cache-paths.bass index c810579b..8da3b342 100644 --- a/pkg/runtimes/testdata/cache-paths.bass +++ b/pkg/runtimes/testdata/cache-paths.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def test-cache-path (cache-dir (str "test-cache-paths-" (now 0)))) diff --git a/pkg/runtimes/testdata/cache-sync.bass b/pkg/runtimes/testdata/cache-sync.bass index b2a50337..0e0805d5 100644 --- a/pkg/runtimes/testdata/cache-sync.bass +++ b/pkg/runtimes/testdata/cache-sync.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def test-cache-path (cache-dir (str "test-cache-sync-" (now 0)))) diff --git a/pkg/runtimes/testdata/dir.bass b/pkg/runtimes/testdata/dir.bass index 97d54db6..de8d845c 100644 --- a/pkg/runtimes/testdata/dir.bass +++ b/pkg/runtimes/testdata/dir.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (next (read (-> (./cat 42) (with-dir /bin/) (with-image (linux/alpine))) diff --git a/pkg/runtimes/testdata/env.bass b/pkg/runtimes/testdata/env.bass index ae50b2db..7ed11c81 100644 --- a/pkg/runtimes/testdata/env.bass +++ b/pkg/runtimes/testdata/env.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (next (read (-> ($ sh -c "echo $FOO") (with-env {:FOO "42"}) (with-image (linux/alpine))) diff --git a/pkg/runtimes/testdata/fs-paths.bass b/pkg/runtimes/testdata/fs-paths.bass index ef20173b..88845851 100644 --- a/pkg/runtimes/testdata/fs-paths.bass +++ b/pkg/runtimes/testdata/fs-paths.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def fs (mkfs ./foo "1\n" ./bar/baz "2\n" diff --git a/pkg/runtimes/testdata/host-paths-sparse.bass b/pkg/runtimes/testdata/host-paths-sparse.bass index c319be3c..d390f606 100644 --- a/pkg/runtimes/testdata/host-paths-sparse.bass +++ b/pkg/runtimes/testdata/host-paths-sparse.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def cat-files (from (linux/alpine) ($ cat diff --git a/pkg/runtimes/testdata/host-paths.bass b/pkg/runtimes/testdata/host-paths.bass index b3c1cf1a..c3e2dc12 100644 --- a/pkg/runtimes/testdata/host-paths.bass +++ b/pkg/runtimes/testdata/host-paths.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def thunk-arg (from (linux/alpine) ($ cat *dir*/host-paths/one))) diff --git a/pkg/runtimes/testdata/many-layers-workdir.bass b/pkg/runtimes/testdata/many-layers-workdir.bass index 9e83c337..b5a01a4a 100644 --- a/pkg/runtimes/testdata/many-layers-workdir.bass +++ b/pkg/runtimes/testdata/many-layers-workdir.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def many-layers (from (linux/alpine) ($ sh -c "echo 1 > a") diff --git a/pkg/runtimes/testdata/mount-run-dir.bass b/pkg/runtimes/testdata/mount-run-dir.bass index 11deb9c5..9c37cb4a 100644 --- a/pkg/runtimes/testdata/mount-run-dir.bass +++ b/pkg/runtimes/testdata/mount-run-dir.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def created (from (linux/alpine) ($ mkdir ./some-dir/) diff --git a/pkg/runtimes/testdata/mount.bass b/pkg/runtimes/testdata/mount.bass index bcda5bd7..74db60d7 100644 --- a/pkg/runtimes/testdata/mount.bass +++ b/pkg/runtimes/testdata/mount.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def created (from (linux/alpine) ($ mkdir ./some-dir/) diff --git a/pkg/runtimes/testdata/multi-env.bass b/pkg/runtimes/testdata/multi-env.bass index ae94bd96..4d7c6ecd 100644 --- a/pkg/runtimes/testdata/multi-env.bass +++ b/pkg/runtimes/testdata/multi-env.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (let [echo-envs (-> ($ sh -c "echo $FOO $BAR") (with-env {:FOO "42" :BAR "21"}) (with-image (linux/alpine))) diff --git a/pkg/runtimes/testdata/oci-archive-image.bass b/pkg/runtimes/testdata/oci-archive-image.bass index 008ff78a..63ad4d99 100644 --- a/pkg/runtimes/testdata/oci-archive-image.bass +++ b/pkg/runtimes/testdata/oci-archive-image.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def go-archive (subpath (from (linux/alpine) diff --git a/pkg/runtimes/testdata/read-path.bass b/pkg/runtimes/testdata/read-path.bass index e3757d32..2a4c7b48 100644 --- a/pkg/runtimes/testdata/read-path.bass +++ b/pkg/runtimes/testdata/read-path.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (defn echo [content] (-> ($ sh -c "echo \"$1\" > file" sh $content) (with-image (linux/alpine)) diff --git a/pkg/runtimes/testdata/recursive.bass b/pkg/runtimes/testdata/recursive.bass index 4f78b069..f51ebccf 100644 --- a/pkg/runtimes/testdata/recursive.bass +++ b/pkg/runtimes/testdata/recursive.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def create (from (linux/alpine) ($ sh -c "echo 42 > hello"))) diff --git a/pkg/runtimes/testdata/remount-workdir-subdir.bass b/pkg/runtimes/testdata/remount-workdir-subdir.bass index af58dd1a..3f045faa 100644 --- a/pkg/runtimes/testdata/remount-workdir-subdir.bass +++ b/pkg/runtimes/testdata/remount-workdir-subdir.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def initial (subpath (from (linux/alpine) diff --git a/pkg/runtimes/testdata/remount-workdir.bass b/pkg/runtimes/testdata/remount-workdir.bass index 75c9b595..3f9e9661 100644 --- a/pkg/runtimes/testdata/remount-workdir.bass +++ b/pkg/runtimes/testdata/remount-workdir.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def initial (-> ($ touch ./foo) (with-image (linux/alpine)) diff --git a/pkg/runtimes/testdata/response-file.bass b/pkg/runtimes/testdata/response-file.bass index bb5b581b..1b5ecf7d 100644 --- a/pkg/runtimes/testdata/response-file.bass +++ b/pkg/runtimes/testdata/response-file.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def values [null false true 42 "hello" [] [0 "one" -2] {} {:foo "bar"}]) diff --git a/pkg/runtimes/testdata/response-stdout.bass b/pkg/runtimes/testdata/response-stdout.bass index e64c62ab..27d9ef13 100644 --- a/pkg/runtimes/testdata/response-stdout.bass +++ b/pkg/runtimes/testdata/response-stdout.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def values [null false true 42 "hello" [] [0 "one" -2] {} {:foo "bar"}]) diff --git a/pkg/runtimes/testdata/run-thunk-path.bass b/pkg/runtimes/testdata/run-thunk-path.bass index a23b224b..5d8d8662 100644 --- a/pkg/runtimes/testdata/run-thunk-path.bass +++ b/pkg/runtimes/testdata/run-thunk-path.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def hello (from (linux/alpine) ($ sh -c "echo \"#!/bin/sh\n\necho 42\n\" > some-script") diff --git a/pkg/runtimes/testdata/secrets.bass b/pkg/runtimes/testdata/secrets.bass index 34cb6afb..979bc504 100644 --- a/pkg/runtimes/testdata/secrets.bass +++ b/pkg/runtimes/testdata/secrets.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - ; these tests are tricky, since we have to prevent the assertions themselves ; from leaking secrets. so we just test against their hash. diff --git a/pkg/runtimes/testdata/sleep.bass b/pkg/runtimes/testdata/sleep.bass index d57b00ea..0c0af4d7 100644 --- a/pkg/runtimes/testdata/sleep.bass +++ b/pkg/runtimes/testdata/sleep.bass @@ -1,3 +1 @@ -(def *memos* *dir*/bass.lock) - (run (-> ($ sleep "999") (with-label :now (now 1)) (with-image (linux/alpine)))) diff --git a/pkg/runtimes/testdata/succeeds.bass b/pkg/runtimes/testdata/succeeds.bass index 8ab6dfaa..69c188f4 100644 --- a/pkg/runtimes/testdata/succeeds.bass +++ b/pkg/runtimes/testdata/succeeds.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - [(succeeds? (from (linux/alpine) ($ sh -c "exit 1"))) diff --git a/pkg/runtimes/testdata/thunk-path-dir-thunk-path-inputs.bass b/pkg/runtimes/testdata/thunk-path-dir-thunk-path-inputs.bass index 32e95bfa..607c49e6 100644 --- a/pkg/runtimes/testdata/thunk-path-dir-thunk-path-inputs.bass +++ b/pkg/runtimes/testdata/thunk-path-dir-thunk-path-inputs.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def create-dir "mkdir some-dir; echo 1 > some-dir/some-file") diff --git a/pkg/runtimes/testdata/thunk-path-dir.bass b/pkg/runtimes/testdata/thunk-path-dir.bass index 4a6579f2..46d7172a 100644 --- a/pkg/runtimes/testdata/thunk-path-dir.bass +++ b/pkg/runtimes/testdata/thunk-path-dir.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def created (from (linux/alpine) ($ mkdir ./some-dir/) diff --git a/pkg/runtimes/testdata/thunk-path-env.bass b/pkg/runtimes/testdata/thunk-path-env.bass index 10204866..a10b602e 100644 --- a/pkg/runtimes/testdata/thunk-path-env.bass +++ b/pkg/runtimes/testdata/thunk-path-env.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def created (from (linux/alpine) ($ sh -c "echo \"#!/bin/sh\n\necho 42\n\" > some-script") diff --git a/pkg/runtimes/testdata/thunk-path-image.bass b/pkg/runtimes/testdata/thunk-path-image.bass index 414bc40e..c802e3c1 100644 --- a/pkg/runtimes/testdata/thunk-path-image.bass +++ b/pkg/runtimes/testdata/thunk-path-image.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def test (from (linux/alpine) ($ sh -c "echo 42 > foo") diff --git a/pkg/runtimes/testdata/thunk-paths.bass b/pkg/runtimes/testdata/thunk-paths.bass index aeb4cef0..7bd78cc4 100644 --- a/pkg/runtimes/testdata/thunk-paths.bass +++ b/pkg/runtimes/testdata/thunk-paths.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def create-files "echo 42 > foo; mkdir some-dir; echo '\"hello\"' > some-dir/some-file") diff --git a/pkg/runtimes/testdata/timestamps.bass b/pkg/runtimes/testdata/timestamps.bass index 980004e3..f7f46bb6 100644 --- a/pkg/runtimes/testdata/timestamps.bass +++ b/pkg/runtimes/testdata/timestamps.bass @@ -1,5 +1,3 @@ -(def *memos* *dir*/bass.lock) - (def touch (from (linux/alpine) ($ touch ./foo) From 8f6118c5a308b32735755dcd1b07bcd3c57ce657 Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Sun, 9 Apr 2023 18:52:01 -0400 Subject: [PATCH 16/16] introduce ($$) like ($), but uses the entrypoint. it's *almost* sufficient to rely on 'default args' here instead, but the two are for different things at the end of the day. --- hack/test | 2 +- pkg/bass/ground.go | 4 + pkg/bass/proto.go | 1 + pkg/bass/thunk.go | 11 +- pkg/proto/bass.pb.go | 363 +++++++++++++------------ pkg/runtimes/buildkit.go | 17 +- pkg/runtimes/dagger.go | 22 +- pkg/runtimes/testdata/entrypoints.bass | 77 +++--- proto/bass.proto | 1 + std/run.bass | 17 +- 10 files changed, 275 insertions(+), 240 deletions(-) diff --git a/hack/test b/hack/test index d63a39cb..ed3d0d64 100755 --- a/hack/test +++ b/hack/test @@ -7,7 +7,7 @@ git submodule update --init --recursive if which gotestsum 2>&1 >/dev/null; then # run tests - exec gotestsum -f dots -- "$@" + exec gotestsum -f dots "$@" else exec go test "$@" fi diff --git a/pkg/bass/ground.go b/pkg/bass/ground.go index 30ccce6c..d625fa7f 100644 --- a/pkg/bass/ground.go +++ b/pkg/bass/ground.go @@ -677,6 +677,10 @@ func init() { Func("with-default-args", "[thunk args]", (Thunk).WithDefaultArgs), `returns thunk with default args set to args`) + Ground.Set("with-entrypoint-args", + Func("with-entrypoint-args", "[thunk args]", (Thunk).WithEntrypointArgs), + `returns thunk with default args set to args`) + Ground.Set("with-stdin", Func("with-stdin", "[thunk vals]", (Thunk).WithStdin), `returns thunk with stdin set to vals`, diff --git a/pkg/bass/proto.go b/pkg/bass/proto.go index 9707a932..533dfecd 100644 --- a/pkg/bass/proto.go +++ b/pkg/bass/proto.go @@ -348,6 +348,7 @@ func (value Thunk) MarshalProto() (proto.Message, error) { pThunk.ClearEntrypoint = value.ClearEntrypoint pThunk.DefaultArgs = value.DefaultArgs pThunk.ClearDefaultArgs = value.ClearDefaultArgs + pThunk.UseEntrypoint = value.UseEntrypoint for i, v := range value.Stdin { pv, err := MarshalProto(v) diff --git a/pkg/bass/thunk.go b/pkg/bass/thunk.go index d2a4daef..8f48725e 100644 --- a/pkg/bass/thunk.go +++ b/pkg/bass/thunk.go @@ -35,7 +35,8 @@ type Thunk struct { // // If left empty, and the thunk is forced to run via (run), (read), or an // output path, the parent Entrypoint and DefaultArgs are used. - Args []Value `json:"args,omitempty"` + Args []Value `json:"args,omitempty"` + UseEntrypoint bool `json:"use_entrypoint,omitempty"` // Stdin is a list of arbitrary values, which may contain paths, to pass to // the command. @@ -138,6 +139,7 @@ func (thunk *Thunk) UnmarshalProto(msg proto.Message) error { thunk.ClearEntrypoint = p.ClearEntrypoint thunk.DefaultArgs = p.DefaultArgs thunk.ClearDefaultArgs = p.ClearDefaultArgs + thunk.UseEntrypoint = p.UseEntrypoint for i, stdin := range p.Stdin { val, err := FromProto(stdin) @@ -488,6 +490,13 @@ func (thunk Thunk) WithArgs(args []Value) Thunk { return thunk } +// WithEntrypointArgs enables the entrypoint and provides args to it. +func (thunk Thunk) WithEntrypointArgs(args []Value) Thunk { + thunk.Args = args + thunk.UseEntrypoint = true + return thunk +} + // AppendArgs appends to the thunk's arg values. func (thunk Thunk) AppendArgs(args ...Value) Thunk { thunk.Args = append(thunk.Args, args...) diff --git a/pkg/proto/bass.pb.go b/pkg/proto/bass.pb.go index 496b1e28..e75091b6 100644 --- a/pkg/proto/bass.pb.go +++ b/pkg/proto/bass.pb.go @@ -316,6 +316,7 @@ type Thunk struct { ClearEntrypoint bool `protobuf:"varint,13,opt,name=clear_entrypoint,json=clearEntrypoint,proto3" json:"clear_entrypoint,omitempty"` DefaultArgs []string `protobuf:"bytes,14,rep,name=default_args,json=defaultArgs,proto3" json:"default_args,omitempty"` ClearDefaultArgs bool `protobuf:"varint,15,opt,name=clear_default_args,json=clearDefaultArgs,proto3" json:"clear_default_args,omitempty"` + UseEntrypoint bool `protobuf:"varint,16,opt,name=use_entrypoint,json=useEntrypoint,proto3" json:"use_entrypoint,omitempty"` } func (x *Thunk) Reset() { @@ -448,6 +449,13 @@ func (x *Thunk) GetClearDefaultArgs() bool { return false } +func (x *Thunk) GetUseEntrypoint() bool { + if x != nil { + return x.UseEntrypoint + } + return false +} + type ThunkAddr struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2472,7 +2480,7 @@ var file_bass_proto_rawDesc = []byte{ 0x30, 0x0a, 0x0a, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x63, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, - 0x68, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x88, 0x04, 0x0a, 0x05, 0x54, + 0x68, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xaf, 0x04, 0x0a, 0x05, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x26, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, @@ -2505,181 +2513,184 @@ var file_bass_proto_rawDesc = []byte{ 0x75, 0x6c, 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x41, 0x72, 0x67, 0x73, 0x22, 0x5a, 0x0a, 0x09, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x41, 0x64, - 0x64, 0x72, 0x12, 0x21, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x52, 0x05, - 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, - 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x22, 0x33, 0x0a, 0x09, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x50, 0x0a, 0x08, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x54, - 0x4c, 0x53, 0x12, 0x22, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, - 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x12, 0x20, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x50, - 0x61, 0x74, 0x68, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xcb, 0x01, 0x0a, 0x0a, 0x54, 0x68, 0x75, - 0x6e, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x49, 0x6d, 0x61, 0x67, - 0x65, 0x52, 0x65, 0x66, 0x48, 0x00, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x23, 0x0a, 0x05, 0x74, - 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, - 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x48, 0x00, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, - 0x12, 0x2e, 0x0a, 0x07, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x41, 0x72, - 0x63, 0x68, 0x69, 0x76, 0x65, 0x48, 0x00, 0x52, 0x07, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, - 0x12, 0x3b, 0x0a, 0x0c, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x49, 0x6d, - 0x61, 0x67, 0x65, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x48, 0x00, - 0x52, 0x0b, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x42, 0x07, 0x0a, - 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0xfb, 0x01, 0x0a, 0x08, 0x49, 0x6d, 0x61, 0x67, 0x65, - 0x52, 0x65, 0x66, 0x12, 0x2a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x50, 0x6c, 0x61, - 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, - 0x20, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, - 0x79, 0x12, 0x29, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, - 0x42, 0x02, 0x18, 0x01, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x04, - 0x61, 0x64, 0x64, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, - 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x48, 0x00, 0x52, 0x04, 0x61, - 0x64, 0x64, 0x72, 0x12, 0x15, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x01, 0x52, 0x03, 0x74, 0x61, 0x67, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x64, 0x69, - 0x67, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x06, 0x64, 0x69, - 0x67, 0x65, 0x73, 0x74, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x74, 0x61, 0x67, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x64, 0x69, - 0x67, 0x65, 0x73, 0x74, 0x22, 0x7e, 0x0a, 0x0c, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x41, 0x72, 0x63, - 0x68, 0x69, 0x76, 0x65, 0x12, 0x2a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x50, 0x6c, - 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, - 0x12, 0x23, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, - 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x52, - 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x15, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67, 0x88, 0x01, 0x01, 0x42, 0x06, 0x0a, 0x04, - 0x5f, 0x74, 0x61, 0x67, 0x22, 0xef, 0x01, 0x0a, 0x10, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x6f, - 0x63, 0x6b, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x2a, 0x0a, 0x08, 0x70, 0x6c, 0x61, - 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, - 0x73, 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, - 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x2f, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x49, 0x6d, - 0x61, 0x67, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x07, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x23, 0x0a, 0x0a, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, - 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x6f, - 0x63, 0x6b, 0x65, 0x72, 0x66, 0x69, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x06, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, - 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x42, 0x75, - 0x69, 0x6c, 0x64, 0x41, 0x72, 0x67, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x42, 0x0d, 0x0a, 0x0b, - 0x5f, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x98, 0x01, 0x0a, 0x0f, 0x49, 0x6d, 0x61, 0x67, 0x65, - 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x27, 0x0a, 0x05, 0x74, 0x68, - 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, - 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x74, 0x68, - 0x75, 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x61, 0x74, - 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x07, 0x6c, 0x6f, 0x67, - 0x69, 0x63, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x61, 0x73, - 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, - 0x07, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x42, 0x07, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, - 0x74, 0x22, 0x34, 0x0a, 0x08, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x41, 0x72, 0x67, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2e, 0x0a, 0x08, 0x50, 0x6c, 0x61, 0x74, 0x66, - 0x6f, 0x72, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x6f, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x22, 0x87, 0x01, 0x0a, 0x08, 0x54, 0x68, 0x75, 0x6e, - 0x6b, 0x44, 0x69, 0x72, 0x12, 0x25, 0x0a, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x0c, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x44, 0x69, 0x72, 0x50, 0x61, - 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x05, 0x74, - 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, - 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x74, - 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x61, - 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x42, 0x05, 0x0a, 0x03, 0x64, 0x69, - 0x72, 0x22, 0xeb, 0x01, 0x0a, 0x10, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x6f, 0x75, 0x6e, 0x74, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, - 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, - 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, - 0x62, 0x61, 0x73, 0x73, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, - 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x07, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, - 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x07, 0x6c, 0x6f, 0x67, - 0x69, 0x63, 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x05, 0x63, 0x61, 0x63, 0x68, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, - 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x63, 0x61, 0x63, 0x68, 0x65, 0x12, 0x26, 0x0a, - 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, - 0x62, 0x61, 0x73, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x48, 0x00, 0x52, 0x06, 0x73, - 0x65, 0x63, 0x72, 0x65, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, - 0x6a, 0x0a, 0x0a, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, 0x0a, - 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, - 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2c, 0x0a, - 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, - 0x61, 0x74, 0x68, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x2c, 0x0a, 0x05, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x12, 0x23, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x33, 0x0a, 0x06, 0x4f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x12, 0x29, 0x0a, 0x08, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x42, 0x69, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x44, - 0x0a, 0x07, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6d, - 0x62, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x79, 0x6d, 0x62, 0x6f, - 0x6c, 0x12, 0x21, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0x06, 0x0a, 0x04, 0x4e, 0x75, 0x6c, 0x6c, 0x22, 0x1c, 0x0a, 0x04, - 0x42, 0x6f, 0x6f, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1b, 0x0a, 0x03, 0x49, 0x6e, - 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1e, 0x0a, 0x06, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x45, 0x0a, 0x09, 0x43, 0x61, 0x63, 0x68, 0x65, - 0x50, 0x61, 0x74, 0x68, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x1c, - 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x21, 0x0a, 0x0b, - 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, - 0x1e, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x70, - 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, - 0x1d, 0x0a, 0x07, 0x44, 0x69, 0x72, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x61, - 0x0a, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, - 0x12, 0x24, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, - 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, - 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x03, 0x64, 0x69, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x44, 0x69, 0x72, 0x50, 0x61, - 0x74, 0x68, 0x48, 0x00, 0x52, 0x03, 0x64, 0x69, 0x72, 0x42, 0x06, 0x0a, 0x04, 0x70, 0x61, 0x74, - 0x68, 0x22, 0x58, 0x0a, 0x09, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x12, 0x21, - 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, - 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, - 0x6b, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x4e, 0x0a, 0x08, 0x48, - 0x6f, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0xec, 0x01, 0x0a, 0x0b, - 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x2c, 0x0a, 0x04, 0x66, - 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x61, 0x73, 0x73, - 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x2e, 0x46, 0x69, 0x6c, - 0x65, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x29, 0x0a, 0x03, 0x64, 0x69, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, - 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x2e, 0x44, 0x69, 0x72, 0x48, 0x00, 0x52, - 0x03, 0x64, 0x69, 0x72, 0x1a, 0x34, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x1a, 0x46, 0x0a, 0x03, 0x44, 0x69, - 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, - 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, - 0x65, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x42, 0x0b, 0x5a, 0x09, 0x70, 0x6b, - 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x75, 0x73, 0x65, 0x5f, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x75, + 0x73, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0x5a, 0x0a, 0x09, + 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x12, 0x21, 0x0a, 0x05, 0x74, 0x68, 0x75, + 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, + 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, + 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, + 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x33, 0x0a, 0x09, 0x54, 0x68, 0x75, 0x6e, + 0x6b, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x50, 0x0a, + 0x08, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x54, 0x4c, 0x53, 0x12, 0x22, 0x0a, 0x04, 0x63, 0x65, 0x72, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, + 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x12, 0x20, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, + 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, + 0xcb, 0x01, 0x0a, 0x0a, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x22, + 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, + 0x73, 0x73, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, 0x48, 0x00, 0x52, 0x03, 0x72, + 0x65, 0x66, 0x12, 0x23, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x48, 0x00, + 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x2e, 0x0a, 0x07, 0x61, 0x72, 0x63, 0x68, 0x69, + 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, + 0x49, 0x6d, 0x61, 0x67, 0x65, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x48, 0x00, 0x52, 0x07, + 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, 0x3b, 0x0a, 0x0c, 0x64, 0x6f, 0x63, 0x6b, 0x65, + 0x72, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, + 0x42, 0x75, 0x69, 0x6c, 0x64, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x42, + 0x75, 0x69, 0x6c, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0xfb, 0x01, + 0x0a, 0x08, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, 0x12, 0x2a, 0x0a, 0x08, 0x70, 0x6c, + 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, + 0x61, 0x73, 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, + 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x20, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x72, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x29, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, + 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x42, 0x02, 0x18, 0x01, 0x48, 0x00, 0x52, 0x04, 0x66, + 0x69, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x41, 0x64, + 0x64, 0x72, 0x48, 0x00, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x15, 0x0a, 0x03, 0x74, 0x61, + 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x03, 0x74, 0x61, 0x67, 0x88, 0x01, + 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x02, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x88, 0x01, 0x01, 0x42, 0x08, + 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x74, 0x61, 0x67, + 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x22, 0x7e, 0x0a, 0x0c, 0x49, + 0x6d, 0x61, 0x67, 0x65, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, 0x2a, 0x0a, 0x08, 0x70, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x23, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, + 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x15, 0x0a, 0x03, + 0x74, 0x61, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67, + 0x88, 0x01, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x74, 0x61, 0x67, 0x22, 0xef, 0x01, 0x0a, 0x10, + 0x49, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, + 0x12, 0x2a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, + 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x2f, 0x0a, 0x07, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, + 0x6e, 0x70, 0x75, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x23, 0x0a, + 0x0a, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x66, 0x69, 0x6c, 0x65, 0x88, + 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x01, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x88, 0x01, 0x01, 0x12, + 0x22, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x41, 0x72, 0x67, 0x52, 0x04, 0x61, + 0x72, 0x67, 0x73, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x66, 0x69, + 0x6c, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x98, 0x01, + 0x0a, 0x0f, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x70, 0x75, + 0x74, 0x12, 0x27, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, + 0x68, 0x48, 0x00, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x68, 0x6f, + 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, + 0x48, 0x6f, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, + 0x12, 0x2d, 0x0a, 0x07, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, + 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x07, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x42, + 0x07, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x34, 0x0a, 0x08, 0x42, 0x75, 0x69, 0x6c, + 0x64, 0x41, 0x72, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2e, + 0x0a, 0x08, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x6f, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, + 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x22, 0x87, + 0x01, 0x0a, 0x08, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x44, 0x69, 0x72, 0x12, 0x25, 0x0a, 0x05, 0x6c, + 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, + 0x73, 0x2e, 0x44, 0x69, 0x72, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x0d, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, + 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x68, + 0x6f, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, + 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x6f, 0x73, + 0x74, 0x42, 0x05, 0x0a, 0x03, 0x64, 0x69, 0x72, 0x22, 0xeb, 0x01, 0x0a, 0x10, 0x54, 0x68, 0x75, + 0x6e, 0x6b, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x27, 0x0a, + 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, + 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, + 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x48, 0x6f, 0x73, 0x74, + 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x07, + 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, + 0x48, 0x00, 0x52, 0x07, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x05, 0x63, + 0x61, 0x63, 0x68, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, + 0x73, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x63, + 0x61, 0x63, 0x68, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x72, + 0x65, 0x74, 0x48, 0x00, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x42, 0x08, 0x0a, 0x06, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x6a, 0x0a, 0x0a, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, + 0x6b, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, + 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x22, 0x2c, 0x0a, 0x05, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x23, 0x0a, 0x06, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, + 0x73, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, + 0x22, 0x33, 0x0a, 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x29, 0x0a, 0x08, 0x62, 0x69, + 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, + 0x61, 0x73, 0x73, 0x2e, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x62, 0x69, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x44, 0x0a, 0x07, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x12, 0x21, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x06, 0x0a, 0x04, 0x4e, + 0x75, 0x6c, 0x6c, 0x22, 0x1c, 0x0a, 0x04, 0x42, 0x6f, 0x6f, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x22, 0x1b, 0x0a, 0x03, 0x49, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1e, + 0x0a, 0x06, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x45, + 0x0a, 0x09, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x28, 0x0a, 0x04, 0x70, + 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, + 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x1c, 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x22, 0x21, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x61, + 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x1e, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, + 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x1d, 0x0a, 0x07, 0x44, 0x69, 0x72, 0x50, 0x61, 0x74, + 0x68, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x61, 0x0a, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, + 0x65, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x21, 0x0a, + 0x03, 0x64, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, + 0x73, 0x2e, 0x44, 0x69, 0x72, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x03, 0x64, 0x69, 0x72, + 0x42, 0x06, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x58, 0x0a, 0x09, 0x54, 0x68, 0x75, 0x6e, + 0x6b, 0x50, 0x61, 0x74, 0x68, 0x12, 0x21, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, + 0x6b, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, + 0x74, 0x68, 0x22, 0x4e, 0x0a, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x18, + 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, + 0x74, 0x68, 0x22, 0xec, 0x01, 0x0a, 0x0b, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, + 0x74, 0x68, 0x12, 0x2c, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x16, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, + 0x61, 0x74, 0x68, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, + 0x12, 0x29, 0x0a, 0x03, 0x64, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, + 0x2e, 0x44, 0x69, 0x72, 0x48, 0x00, 0x52, 0x03, 0x64, 0x69, 0x72, 0x1a, 0x34, 0x0a, 0x04, 0x46, + 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x1a, 0x46, 0x0a, 0x03, 0x44, 0x69, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x07, + 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, + 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x70, 0x61, 0x74, + 0x68, 0x42, 0x0b, 0x5a, 0x09, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/runtimes/buildkit.go b/pkg/runtimes/buildkit.go index 8eebd823..dc7147e1 100644 --- a/pkg/runtimes/buildkit.go +++ b/pkg/runtimes/buildkit.go @@ -803,18 +803,25 @@ func (b *buildkitBuilder) llb( } } + useEntrypoint := thunk.UseEntrypoint if len(cmd.Args) == 0 { if forceExec { - cmd.Args = append(ib.config.Entrypoint, ib.config.Cmd...) - if len(cmd.Args) == 0 { - return ib, fmt.Errorf("no command specified") - } + cmd.Args = ib.config.Cmd + useEntrypoint = true } else { - // no command; we're just overriding config + // no command; just overriding config return ib, nil } } + if useEntrypoint { + cmd.Args = append(ib.config.Entrypoint, cmd.Args...) + } + + if len(cmd.Args) == 0 { + return ib, fmt.Errorf("no command specified") + } + cmdPayload, err := bass.MarshalJSON(cmd) if err != nil { return ib, err diff --git a/pkg/runtimes/dagger.go b/pkg/runtimes/dagger.go index 98d54dc5..9f81c6c5 100644 --- a/pkg/runtimes/dagger.go +++ b/pkg/runtimes/dagger.go @@ -319,13 +319,18 @@ func (runtime *Dagger) container(ctx context.Context, thunk bass.Thunk, forceExe } if len(cmd.Args) > 0 { - ep, err := ctr.Entrypoint(ctx) - if err != nil { - return nil, err - } + var removedEntrypoint bool + var prevEntrypoint []string + if !thunk.UseEntrypoint { + prevEntrypoint, err = ctr.Entrypoint(ctx) + if err != nil { + return nil, err + } - if len(ep) > 0 { - ctr = ctr.WithEntrypoint(nil) + if len(prevEntrypoint) > 0 { + ctr = ctr.WithEntrypoint(nil) + removedEntrypoint = true + } } ctr = ctr.WithExec(cmd.Args, dagger.ContainerWithExecOpts{ @@ -333,8 +338,9 @@ func (runtime *Dagger) container(ctx context.Context, thunk bass.Thunk, forceExe InsecureRootCapabilities: thunk.Insecure, }) - if len(ep) > 0 { - ctr = ctr.WithEntrypoint(ep) + if removedEntrypoint { + // restore previous entrypoint + ctr = ctr.WithEntrypoint(prevEntrypoint) } } else if forceExec { ctr = ctr.WithExec(append(thunk.Entrypoint, thunk.DefaultArgs...)) diff --git a/pkg/runtimes/testdata/entrypoints.bass b/pkg/runtimes/testdata/entrypoints.bass index 715544bf..a11072a8 100644 --- a/pkg/runtimes/testdata/entrypoints.bass +++ b/pkg/runtimes/testdata/entrypoints.bass @@ -5,47 +5,48 @@ (let [config (oci:config thunk)] (:Entrypoint config null))) -(def not-respected - (from (linux/alpine/git :2.36.3) - ($ git --version))) +(defn read-all [thunk] + (next (read thunk :raw))) -; entrypoint is *not* respected by ($) +; entrypoint is not respected by ($) (assert = "git version 2.36.3\n" - (-> not-respected - (read :raw) - next)) + (read-all + (from (linux/alpine/git :2.36.3) + ($ git --version)))) -; but it is preserved in the published image +; entrypoint is respected by ($$) +(assert = "git version 2.36.3\n" + (read-all + (from (linux/alpine/git) + ($$ --version)))) + +; entrypoint is preserved even after ($) ignores it (assert = ["git"] - (entrypoint not-respected)) + (entrypoint + (from (linux/alpine/git) + ($ git --version)))) -; entrypoint *is* respected when running directly -(run (linux/hello-world)) +; entrypoint is used when running image directly +(assert null? + (run (linux/hello-world))) -; or reading +; entrypoint is used when reading output (assert strings:includes? - (-> (linux/hello-world) - (read :raw) - next) + (read-all (linux/hello-world)) "Hello from Docker") -; or accessing a path -(def create-path - (-> (linux/alpine) - (with-entrypoint ["sh" "-c" "echo hello > index.html"]))) - +; entrypoint is used when reading output path (assert = "hello\n" - (-> create-path/index.html - (read :raw) - next)) + (read-all + (-> (linux/alpine) + (with-entrypoint ["sh" "-c" "echo hello > index.html"]) + (subpath ./index.html)))) ; entrypoint is removed when set to empty list -(def unset-image - (-> (linux/alpine/git :2.36.3) - (with-entrypoint []))) - (assert null? - (entrypoint unset-image)) + (entrypoint + (-> (linux/alpine/git :2.36.3) + (with-entrypoint [])))) ; entrypoint can be set by thunk (def touch-and-run @@ -58,19 +59,13 @@ (entrypoint touch-and-run)) ; entrypoint is preserved from thunk to thunk -(def keeps-entrypoint - (from touch-and-run - ($ echo "Hello, world!"))) - (assert = ["httpd" "-f" "-p" "8000"] - (entrypoint keeps-entrypoint)) - -; entrypoint is respected after running a command -(def wget - (from (linux/alpine) - ($ wget -O- (addr touch-and-run :http "http://$host:$port/")))) + (entrypoint + (from touch-and-run + ($ echo "Hello, world!")))) +; entrypoint is still used after running a command (assert = "hello from index.html\n" - (-> wget - (read :raw) - next)) + (read-all + (from (linux/alpine) + ($ wget -O- (addr touch-and-run :http "http://$host:$port/"))))) diff --git a/proto/bass.proto b/proto/bass.proto index e163ee60..eb6d580d 100644 --- a/proto/bass.proto +++ b/proto/bass.proto @@ -39,6 +39,7 @@ message Thunk { bool clear_entrypoint = 13; repeated string default_args = 14; bool clear_default_args = 15; + bool use_entrypoint = 16; }; message ThunkAddr { diff --git a/std/run.bass b/std/run.bass index c07acc18..2ea73f6e 100644 --- a/std/run.bass +++ b/std/run.bass @@ -4,7 +4,7 @@ (defn insecure! [thunk] (with-insecure thunk true)) -(provide ($) +(provide ($ $$) (defn resolve-arg [a scope] (if (symbol? a) (let [word (symbol->string a) @@ -14,12 +14,6 @@ (eval word scope))) (eval a scope))) - (defn resolve-cmd [a scope] - (let [val (resolve-arg a scope)] - (if (string? val) - (string->cmd-path val) - val))) - (defn resolve-args [args scope] (case args [] [] @@ -34,7 +28,14 @@ ; ; => ($ sh -c "echo Hello, world!") (defop $ args scope - (with-args scratch (resolve-args args scope)))) + (with-args scratch (resolve-args args scope))) + + ; constructs a thunk with args passed to its entrypoint + ; + (defop $$ args scope + (with-entrypoint-args scratch (resolve-args args scope))) + + ) ; provide ; chain a sequence of thunks starting from an initial image ;