diff --git a/bass/bass.bass b/bass/bass.bass index 292c651f..c151915d 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))) @@ -27,19 +27,7 @@ (git-out src ($ git 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 ($ git log -n1 "--pretty=format:%H" -- & $paths))) (defn git-submodules [src] (map (fn [[_ path]] (string->dir path)) diff --git a/bass/bass.lock b/bass/bass.lock index 6ce7098f..852c360b 100644 --- a/bass/bass.lock +++ b/bass/bass.lock @@ -1,7 +1,7 @@ memos: { module: { - cmd: { - command: { + args: { + command_path: { name: "run" } } @@ -49,44 +49,16 @@ memos: { } } 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" + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "alpine/git" + tag: "latest" + digest: "sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2" } } } @@ -133,44 +105,16 @@ memos: { } } 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" + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "ubuntu" + tag: "latest" + digest: "sha256:67211c14fa74f070d27cc59d69a7fa9aeff8e28ea118ef3babc295a0428a6d21" } } } @@ -217,44 +161,16 @@ memos: { } } 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" + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "alpine" + tag: "latest" + digest: "sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126" } } } @@ -284,7 +200,7 @@ memos: { symbol: "repository" value: { string: { - value: "moby/buildkit" + value: "squareup/certstrap" } } } @@ -292,7 +208,7 @@ memos: { symbol: "tag" value: { string: { - value: "v0.10.3" + value: "latest" } } } @@ -301,44 +217,16 @@ memos: { } } 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" + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "squareup/certstrap" + tag: "latest" + digest: "sha256:c18a2389cf102a78ed6b42a2ae56ab81d898de30cdf1aca79a16bec15b22f7f2" } } } @@ -368,7 +256,7 @@ memos: { symbol: "repository" value: { string: { - value: "vito/buildkit" + value: "alpine/git" } } } @@ -376,7 +264,7 @@ memos: { symbol: "tag" value: { string: { - value: "v0.10.3-conflist" + value: "2.36.3" } } } @@ -385,44 +273,16 @@ memos: { } } 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" + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "alpine/git" + tag: "2.36.3" + digest: "sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2" } } } @@ -452,7 +312,7 @@ memos: { symbol: "repository" value: { string: { - value: "squareup/certstrap" + value: "registry" } } } @@ -469,270 +329,153 @@ memos: { } } output: { - object: { - bindings: { - symbol: "repository" - value: { - string: { - value: "squareup/certstrap" + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "registry" + tag: "latest" + digest: "sha256:8c51be2f669c82da8015017ff1eae5e5155fcf707ba914c5c7b798fbeb03b50c" } } - bindings: { - symbol: "platform" - value: { - object: { - bindings: { - symbol: "os" - value: { - string: { - value: "linux" + } + } + } + results: { + input: { + array: { + values: { + object: { + 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" + bindings: { + symbol: "repository" + value: { + string: { + value: "busybox" + } + } } - } - } - } - } - } - } -} -memos: { - module: { - cmd: { - command: { - name: "git" - } - } - stdin: { - object: { - bindings: { - symbol: "platform" - value: { - object: { bindings: { - symbol: "os" + symbol: "tag" value: { string: { - value: "linux" + value: "latest" } } } } } } - 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: { + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" + } + repository: "busybox" + tag: "latest" + digest: "sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" } } } } - 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" + symbol: "platform" + value: { + object: { + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } + } + } + } + } + bindings: { + symbol: "repository" value: { string: { - value: "linux" + value: "hello-world" + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" } } } - } - } - } - 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: { + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" + } + repository: "hello-world" + tag: "latest" + digest: "sha256:ffb13da98453e0f04d33a6eee5bb8e46ee50d08ebe17735fc0779d0349e889e9" } } } } - output: { - string: { - value: "c97bdc3bc41acb5c1bebec6fba9994ee2fb992a5" - } - } } } } memos: { module: { - cmd: { - command: { + args: { + command_path: { 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" + thunk: { + image: { + ref: { + platform: { + os: "linux" + arch: "amd64" } + repository: "alpine/git" + tag: "latest" + digest: "sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2" } } } @@ -757,71 +500,16 @@ memos: { } 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" - } - } + value: "6ca3f15d70b739a7929886e20b61dbc4cbdc4e22" } } } - } - calls: { - binding: "ls-remote" results: { input: { array: { values: { string: { - value: "https://github.com/vito/tabs" + value: "https://github.com/vito/bass-loop" } } values: { @@ -833,7 +521,7 @@ memos: { } output: { string: { - value: "c97bdc3bc41acb5c1bebec6fba9994ee2fb992a5" + value: "0fd154b53db44c0dced9b61092db79953d69bd13" } } } 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/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/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/docs/lit/index.lit b/docs/lit/index.lit index 363b1ccc..226ef5a0 100644 --- a/docs/lit/index.lit +++ b/docs/lit/index.lit @@ -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/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/cache_path.go b/pkg/bass/cache_path.go index 7683d71b..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 @@ -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..f76393a6 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, }, @@ -240,6 +239,10 @@ var validThunkImageArchives = []bass.ImageArchive{ }, } +func ptr[T any](v T) *T { + return &v +} + var validThunkImageDockerBuilds = []bass.ImageDockerBuild{ { Platform: bass.Platform{ @@ -252,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"), @@ -312,34 +315,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/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/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/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 98ec6e9d..91aa5227 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} @@ -142,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/ground.go b/pkg/bass/ground.go index 2fab4a3f..d625fa7f 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,17 @@ 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-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), @@ -710,14 +719,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...) @@ -734,10 +735,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/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..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 @@ -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..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 @@ -234,9 +234,7 @@ var _ Applicative = FilePath{} func (app FilePath) Unwrap() Combiner { return ThunkOperative{ - Cmd: ThunkCmd{ - File: &app, - }, + Cmd: app, } } @@ -340,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 @@ -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..533dfecd 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 { @@ -141,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 } @@ -316,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, } @@ -326,32 +332,31 @@ func (value Thunk) MarshalProto() (proto.Message, error) { return nil, fmt.Errorf("image: %w", err) } - thunk.Image = ti.(*proto.ThunkImage) - } - - ci, err := value.Cmd.MarshalProto() - if err != nil { - return nil, fmt.Errorf("command: %w", err) + pThunk.Image = ti.(*proto.ThunkImage) } - thunk.Cmd = ci.(*proto.ThunkCmd) - for i, v := range value.Args { pv, err := MarshalProto(v) if err != nil { 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 + pThunk.UseEntrypoint = value.UseEntrypoint + 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 { @@ -361,7 +366,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, }) @@ -378,7 +383,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 { @@ -387,7 +392,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 { @@ -397,7 +402,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, }) @@ -409,7 +414,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), }) @@ -426,13 +431,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/secret.go b/pkg/bass/secret.go index ccbc29ad..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 { @@ -83,7 +81,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/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..8f48725e 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" @@ -21,17 +22,21 @@ 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 // 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 []Value `json:"args,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"` + UseEntrypoint bool `json:"use_entrypoint,omitempty"` // Stdin is a list of arbitrary values, which may contain paths, to pass to // the command. @@ -78,6 +83,22 @@ 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 any command the published container runs. + // + // 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"` + 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"` + ClearDefaultArgs bool `json:"clear_default_args,omitempty"` } type ThunkPort struct { @@ -93,7 +114,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 { @@ -105,12 +126,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 { @@ -120,6 +135,12 @@ 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 + thunk.UseEntrypoint = p.UseEntrypoint + for i, stdin := range p.Stdin { val, err := FromProto(stdin) if err != nil { @@ -197,13 +218,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 +241,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("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("cannot infer run dir from command %s: %s", cmd, thunk)) + } +} + func (thunk Thunk) Read(ctx context.Context, w io.Writer) error { platform := thunk.Platform() @@ -370,14 +416,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,18 +443,60 @@ 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 = 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 { + 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 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...) @@ -493,7 +573,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 %s: %s}}", thunk.Name(), thunk.Cmdline()) } func (thunk Thunk) Equal(other Value) bool { 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 d68aecc6..30990b49 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 { @@ -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} @@ -161,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_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..58b5ce68 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. @@ -20,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 { @@ -69,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") @@ -91,7 +98,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 { @@ -180,7 +187,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 @@ -211,7 +218,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) { @@ -365,7 +372,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 { @@ -551,230 +558,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 @@ -784,7 +567,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) { @@ -954,7 +737,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 { @@ -1001,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"` @@ -1016,7 +799,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 { @@ -1028,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() @@ -1056,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 } @@ -1068,7 +880,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) { diff --git a/pkg/bass/value_test.go b/pkg/bass/value_test.go index 7d3784de..5218842a 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/", + "{{thunk CBA5NVSCDITAM: ./file}}/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..e75091b6 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,22 +295,28 @@ func (*Value_LogicalPath) isValue_Value() {} func (*Value_ThunkAddr) isValue_Value() {} +func (*Value_CachePath) isValue_Value() {} + type Thunk struct { state protoimpl.MessageState 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"` - 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"` - 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"` + UseEntrypoint bool `protobuf:"varint,16,opt,name=use_entrypoint,json=useEntrypoint,proto3" json:"use_entrypoint,omitempty"` } func (x *Thunk) Reset() { @@ -347,13 +365,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 @@ -410,6 +421,41 @@ 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 +} + +func (x *Thunk) GetUseEntrypoint() bool { + if x != nil { + return x.UseEntrypoint + } + return false +} + type ThunkAddr struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1160,143 +1206,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 +1222,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 +1235,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 +1248,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 +1319,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 +1332,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 +1345,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 +1436,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 +1449,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 +1462,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 +1490,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 +1503,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 +1516,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 +1537,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 +1550,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 +1563,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 +1585,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 +1598,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 +1611,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 +1637,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 +1650,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 +1663,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 +1677,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 +1690,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 +1703,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 +1724,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 +1737,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 +1750,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 +1771,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 +1784,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 +1797,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 +1819,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 +1832,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 +1845,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 +1873,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 +1886,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 +1899,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 +1920,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 +1933,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 +1946,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 +1967,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 +1980,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 +1993,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 +2014,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 +2027,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 +2040,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 +2065,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 +2078,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 +2091,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 +2143,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 +2156,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 +2169,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 +2198,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 +2211,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 +2224,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 +2256,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 +2269,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 +2282,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 +2334,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 +2347,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 +2360,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 +2389,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 +2402,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 +2415,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 +2436,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 +2476,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, 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, + 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, @@ -2593,199 +2503,194 @@ 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, 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, + 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, 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, 0x04, + 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, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 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, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, + 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, 0x42, 0x05, 0x0a, 0x03, 0x63, 0x6d, 0x64, 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, + 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, 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, + 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, - 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, + 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 ( @@ -2800,7 +2705,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 +2719,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 +2965,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 +2976,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 +2988,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 +3000,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 +3012,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 +3024,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 +3036,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 +3048,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 +3060,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 +3072,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 +3084,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 +3096,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 +3108,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 +3120,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 +3132,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 +3144,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 +3156,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 +3168,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 +3180,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 +3192,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 +3204,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 +3233,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 +3254,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 +3279,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/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/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..dc7147e1 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 { @@ -262,10 +262,11 @@ 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 + nil, // exports + true, // inherit entrypoint/cmd ) return err } @@ -290,10 +291,11 @@ 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 + nil, // exports + true, // inherit entrypoint/cmd ) exited <- err @@ -345,7 +347,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{ @@ -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 { @@ -383,7 +386,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, @@ -392,6 +397,7 @@ func (runtime *Buildkit) Export(ctx context.Context, w io.Writer, thunk bass.Thu }, }, }, + false, // do not inherit entrypoint/cmd ) return err } @@ -408,7 +414,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, @@ -418,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 @@ -441,7 +450,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 @@ -460,6 +469,7 @@ func (runtime *Buildkit) ExportPath(ctx context.Context, w io.Writer, tp bass.Th }, }, }, + true, // inherit entryopint/cmd ) return err } @@ -518,13 +528,15 @@ 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, + forceExec bool, 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 +548,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, forceExec, 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 +572,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 +583,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 +746,101 @@ 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, + forceExec bool, + 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 + } + + // propagate thunk's entrypoint to the child + if len(thunk.Entrypoint) > 0 || thunk.ClearEntrypoint { + ib.config.Entrypoint = thunk.Entrypoint + } + + // propagate thunk's default command + if len(thunk.DefaultArgs) > 0 || thunk.ClearDefaultArgs { + 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 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{}{} + } + } + + useEntrypoint := thunk.UseEntrypoint + if len(cmd.Args) == 0 { + if forceExec { + cmd.Args = ib.config.Cmd + useEntrypoint = true + } else { + // 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 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 +857,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 +903,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 +921,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 +952,11 @@ 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 + + return ib, nil } func (runtime *Buildkit) shim() (llb.State, error) { @@ -900,38 +999,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 + + sourcePath string + needsInsecure bool + + config ocispecs.ImageConfig +} - if image.Ref != nil { +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() + } + + 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, + }) + } - if image.Archive != nil { + 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, false) + + 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 +1092,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 +1101,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 +1140,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 +1176,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{ @@ -1032,7 +1186,7 @@ func (b *buildkitBuilder) image(ctx context.Context, image *bass.ThunkImage) (ll const defaultDockerfileName = "Dockerfile" - if dockerfile.Path != "" { + if dockerfile != nil { opts["filename"] = path.Join(sourcePath, dockerfile.Slash()) } else { opts["filename"] = path.Join(sourcePath, defaultDockerfileName) @@ -1053,13 +1207,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 +1274,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 +1360,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, true) 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 +1545,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/dagger.go b/pkg/runtimes/dagger.go index 1f21f849..9f81c6c5 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 @@ -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() @@ -277,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 } @@ -319,10 +318,45 @@ func (runtime *Dagger) container(ctx context.Context, thunk bass.Thunk) (*dagger ctr = ctr.WithSecretVariable(env.Name, secret) } - return ctr.WithExec(cmd.Args, dagger.ContainerWithExecOpts{ - Stdin: string(cmd.Stdin), - InsecureRootCapabilities: thunk.Insecure, - }), nil + if len(cmd.Args) > 0 { + var removedEntrypoint bool + var prevEntrypoint []string + if !thunk.UseEntrypoint { + prevEntrypoint, err = ctr.Entrypoint(ctx) + if err != nil { + return nil, err + } + + if len(prevEntrypoint) > 0 { + ctr = ctr.WithEntrypoint(nil) + removedEntrypoint = true + } + } + + ctr = ctr.WithExec(cmd.Args, dagger.ContainerWithExecOpts{ + Stdin: string(cmd.Stdin), + InsecureRootCapabilities: thunk.Insecure, + }) + + if removedEntrypoint { + // restore previous entrypoint + ctr = ctr.WithEntrypoint(prevEntrypoint) + } + } else if forceExec { + ctr = ctr.WithExec(append(thunk.Entrypoint, thunk.DefaultArgs...)) + } + + if len(thunk.Entrypoint) > 0 || thunk.ClearEntrypoint { + ctr = ctr.WithEntrypoint(thunk.Entrypoint) + } + + if len(thunk.DefaultArgs) > 0 || thunk.ClearDefaultArgs { + ctr = ctr.WithDefaultArgs(dagger.ContainerWithDefaultArgsOpts{ + Args: thunk.DefaultArgs, + }) + } + + return ctr, nil } var epoch = time.Date(1985, 10, 26, 8, 15, 0, 0, time.UTC) @@ -334,7 +368,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 } @@ -428,7 +462,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 8c16fa76..b7f57b48 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,21 +24,49 @@ type Client struct { var _ bass.Runtime = &Client{} -func (client *Client) Resolve(ctx context.Context, ref bass.ImageRef) (bass.ImageRef, error) { - ret := bass.ImageRef{} +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.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 @@ -245,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) @@ -263,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/grpc_test.go b/pkg/runtimes/grpc_test.go new file mode 100644 index 00000000..cd2e803c --- /dev/null +++ b/pkg/runtimes/grpc_test.go @@ -0,0 +1,81 @@ +package runtimes_test + +import ( + "context" + "errors" + "net" + "os" + "path/filepath" + "testing" + + "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) + is.New(t).NoErr(err) + + defer listener.Close() + + ctx := context.Background() + + pool, err := runtimes.NewPool(ctx, &bass.Config{ + Runtimes: []bass.RuntimeConfig{ + { + Platform: bass.LinuxPlatform, + Runtime: runtimes.BuildkitName, + Config: config.Scope(), + }, + }, + }) + is.New(t).NoErr(err) + + ctx = bass.WithRuntimePool(ctx, pool) + + 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(), + }, runtimes.SkipSuites( + // secrets don't get sent over gRPC + "secrets.bass", + )) +} diff --git a/pkg/runtimes/suite.go b/pkg/runtimes/suite.go index de348195..355a684a 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) @@ -205,8 +210,7 @@ func Suite(t *testing.T, config bass.RuntimeConfig) { ), }, { - File: "oci-archive-image.bass", - Result: bass.String("/go"), + File: "oci-archive-image.bass", }, { File: "remount-workdir.bass", @@ -233,16 +237,13 @@ func Suite(t *testing.T, config bass.RuntimeConfig) { 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", - 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) @@ -290,17 +291,18 @@ func Suite(t *testing.T, config bass.RuntimeConfig) { // 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", }, } { 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() @@ -314,12 +316,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) @@ -363,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 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/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/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 new file mode 100644 index 00000000..a11072a8 --- /dev/null +++ b/pkg/runtimes/testdata/entrypoints.bass @@ -0,0 +1,71 @@ +(use (.strings) + (*dir*/lib/oci.bass)) + +(defn entrypoint [thunk] + (let [config (oci:config thunk)] + (:Entrypoint config null))) + +(defn read-all [thunk] + (next (read thunk :raw))) + +; entrypoint is not respected by ($) +(assert = "git version 2.36.3\n" + (read-all + (from (linux/alpine/git :2.36.3) + ($ git --version)))) + +; 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 + (from (linux/alpine/git) + ($ git --version)))) + +; entrypoint is used when running image directly +(assert null? + (run (linux/hello-world))) + +; entrypoint is used when reading output +(assert strings:includes? + (read-all (linux/hello-world)) + "Hello from Docker") + +; entrypoint is used when reading output path +(assert = "hello\n" + (read-all + (-> (linux/alpine) + (with-entrypoint ["sh" "-c" "echo hello > index.html"]) + (subpath ./index.html)))) + +; entrypoint is removed when set to empty list +(assert null? + (entrypoint + (-> (linux/alpine/git :2.36.3) + (with-entrypoint [])))) + +; entrypoint can be set by thunk +(def touch-and-run + (-> (from (linux/busybox) + ($ sh -c "echo hello from index.html > index.html")) + (with-port :http 8000) + (with-entrypoint ["httpd" "-f" "-p" "8000"]))) + +(assert = ["httpd" "-f" "-p" "8000"] + (entrypoint touch-and-run)) + +; entrypoint is preserved from thunk to thunk +(assert = ["httpd" "-f" "-p" "8000"] + (entrypoint + (from touch-and-run + ($ echo "Hello, world!")))) + +; entrypoint is still used after running a command +(assert = "hello from index.html\n" + (read-all + (from (linux/alpine) + ($ wget -O- (addr touch-and-run :http "http://$host:$port/"))))) 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/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/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 03fb44dd..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) @@ -8,11 +6,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/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 ca55cf1d..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. @@ -26,5 +24,3 @@ (map assert-export-does-not-contain-secret [stdin-secret env-secret file-secret]) - -null 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) 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 1c55e076..eb6d580d 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; @@ -35,6 +35,11 @@ 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; + bool use_entrypoint = 16; }; message ThunkAddr { @@ -105,17 +110,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; @@ -173,6 +167,8 @@ message CachePath { message Secret { string name = 1; + // NB: secrets values are intentionally omitted. + // string secret = 2; }; message CommandPath { 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/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..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 [] [] @@ -33,10 +27,15 @@ ; 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))) + + ; 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 ; @@ -65,11 +64,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] @@ -136,8 +133,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: ; @@ -155,7 +151,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))