diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0a0e9093..e4d73578 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,8 +7,8 @@ whether that's writing code or just providing good signals to the project. ## Contributing feedback & discussions Languages evolve as more people speak them. Bass is very young, so feedback is -incredibly valuable. Using it for my own projects has led to dramatic changes, -and it'd be best to get the bulk of these out of the way early on. +incredibly valuable. Using it for my own projects has led to dramatic changes +to Bass, and it'd be best to get the bulk of these out of the way early on. The best place to leave feedback is in [Discussions], but feel free to just hop in [Discord] too. @@ -16,7 +16,7 @@ in [Discord] too. It's hard to use a language without having something to say, so if you don't have a project to apply Bass to feel free to critique Bass's own Bass code: -* [project.bass](project.bass) contains the bulk of the project code. +* [bass/bass.bass](bass/bass.bass) contains the bulk of the project code. * [bass/build](bass/build) builds Bass binaries. * [bass/docs](bass/docs) builds Bass's docs. * [bass/test](bass/test) runs Bass's test suite. @@ -74,9 +74,7 @@ this is a debt that I won't let grow out of control. To run the tests: ```sh -# for lsp, which have a lsp config submodule for lsp config -git submodule update --init --recursive -go test ./... +./hack/test ``` The tests assume Buildkit is running somewhere, and they discover it the same diff --git a/Makefile b/Makefile index fab34762..bacd580b 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ shims=$(foreach arch,$(arches),pkg/runtimes/bin/exe.$(arch)) all: cmd/bass/bass -pkg/runtimes/bin/exe.%: pkg/runtimes/shim/main.go +pkg/runtimes/bin/exe.%: pkg/runtimes/shim/*.go env GOOS=linux GOARCH=$* CGO_ENABLED=0 go build -ldflags "-s -w" -o $@ ./pkg/runtimes/shim cmd/bass/bass: shims diff --git a/bass/bass.bass b/bass/bass.bass index 6ae6e17a..d63dcb70 100644 --- a/bass/bass.bass +++ b/bass/bass.bass @@ -129,15 +129,22 @@ (map (fn [image] (check-dist dist image)) smoke-tests)) - (defn test-buildkit [os arch] - (-> ($ buildkitd --addr "tcp://0.0.0.0:6107") - (with-image (buildkit:image os arch buildkit:test-config)) - (with-mount (cache-dir "bass buildkitd") /var/lib/buildkit/) - (with-port :grpc 6107) - insecure!)) + (defn test-buildkit [os arch cert] + (let [resolv (str "nameserver 10.73.0.1\n" + "nameserver 1.1.1.1\n" + "search dns.bass\n")] + (from (buildkit:image os arch buildkit:test-config) + ($ cp $cert /etc/ssl/certs/bass.crt) + ($ chmod "0400" /etc/ssl/certs/bass.crt) + (-> ($ buildkitd --addr "tcp://0.0.0.0:6107") + (with-mount (cache-dir "bass buildkitd") /var/lib/buildkit/) + (with-mount (mkfile ./resolv.conf resolv) /etc/resolv.conf) + (with-port :grpc 6107) + insecure!)))) (defn with-bass-and-buildkitd [thunk src] - (let [buildkit-host (addr (test-buildkit "linux" "amd64") :grpc "tcp://$host:$port") + (let [buildkit (test-buildkit "linux" "amd64" src/pkg/runtimes/testdata/tls/bass.crt) + buildkit-host (addr buildkit :grpc "tcp://$host:$port") built-bass (dist src "dev" "linux" "amd64")] (-> thunk (with-env {:BUILDKIT_HOST buildkit-host}) diff --git a/bass/buildkit.bass b/bass/buildkit.bass index 8be7963a..5e8861f6 100644 --- a/bass/buildkit.bass +++ b/bass/buildkit.bass @@ -1,9 +1,7 @@ -; bumped by hack/bump-buildkit -(def *buildkit-version* "v0.10.3") +(def *buildkit-repository* "moby/buildkit") -; TODO: move back to upstream once PRs are merged -(def *buildkit-repository* "vito/buildkit") -(def *buildkit-variant* "-conflist-hostname") +; bumped by hack/bump-buildkit +(def *buildkit-tag* "master") ; TODO: go back to a pinned version (def *cni-version* "v1.1.1") @@ -13,17 +11,17 @@ (defn image [os arch config-dir] (from (resolve {:platform {:os os} ; TODO: :arch arch} :repository *buildkit-repository* - :tag (str *buildkit-version* *buildkit-variant*)}) + :tag *buildkit-tag*}) ($ apk add --no-cache dumb-init iptables ip6tables dnsmasq) ; TODO: nix? ($ mkdir -p /opt/cni/bin/ /etc/buildkit/) ($ cp $dnsname /opt/cni/bin/dnsname) ($ tar -zxf (cni os arch) -C /opt/cni/bin/) ($ sh -c "cp $0/* /etc/buildkit/" $config-dir))) - (defn buildkitd-toml [cni-path dns] + (defn buildkitd-toml [cni-path] (str "# support insecure! thunks\n" - "insecure-entitlements = [ \"security.insecure\" ]\n" + "insecure-entitlements = [\"security.insecure\"]\n" "\n" "# configure bridge networking\n" "[worker.oci]\n" @@ -32,10 +30,7 @@ "\n" "[worker.containerd]\n" "networkMode = \"cni\"\n" - "cniConfigPath = \"" (/etc/buildkit/ cni-path) "\"\n" - "\n" - "[dns]\n" - "nameservers = [\"" dns "\"]\n")) + "cniConfigPath = \"" (/etc/buildkit/ cni-path) "\"\n")) (def dnsname (subpath @@ -76,9 +71,14 @@ (def bass-config (mkfs ./bass.conflist (json (cni-config "bass" "10.64.0.0/16")) - ./buildkitd.toml (buildkitd-toml ./bass.conflist "10.64.0.1"))) + ./buildkitd.toml (buildkitd-toml ./bass.conflist))) (def test-config (mkfs ./test.conflist (json (cni-config "bass" "10.73.0.0/16")) - ./buildkitd.toml (buildkitd-toml ./test.conflist "10.73.0.1")))) + ./buildkitd.toml (str (buildkitd-toml ./test.conflist) + "\n" + ; override the default nameserver + "[dns]\n" + "nameservers = [\"10.73.0.1\", \"1.1.1.1\"]\n"))) + ) diff --git a/demos/registry-mirror.bass b/demos/registry-mirror.bass new file mode 100644 index 00000000..046a44a5 --- /dev/null +++ b/demos/registry-mirror.bass @@ -0,0 +1,48 @@ +(use (.strings)) + +(def config + {:version "0.1" + :http {:addr "0.0.0.0:5000" + :tls {:certificate "/registry.crt" + :key "/registry.key"}} + :storage {:filesystem {:rootdirectory "/var/lib/registry"}} + :proxy {:remoteurl "https://registry-1.docker.io"}}) + +(def mirror + (-> ($ registry serve (mkfile ./config.yml (json config))) + (with-image (linux/registry)) + (with-mount (cache-dir "registry-mirror") /var/lib/registry/) + (with-tls /registry.crt /registry.key) + (with-port :http 5000))) + +(defn resolver [thunk platform names] + (fn optional + (case optional + [] + (let [expand (case names [lib] ["library" lib] _ names) + repository (str "$host:$port/" (strings:join "/" expand))] + (resolve {:platform platform + :repository (addr thunk :http repository) + :tag "latest"})) + + [dep] + (resolver thunk platform (conj names (path-name dep))) + + _ + (error "invalid image path segment" :segment optional)))) + +(def xunil + (resolver mirror {:os "linux"} [])) + +(defn main [] + ; buildkit -> thunk TLS + (-> ($ echo "I'm mirrored!") + (with-image (xunil/alpine)) + run) + + ; thunk -> thunk TLS + (-> ($ wget -O- (addr mirror :http "https://$host:$port/v2/library/alpine/manifests/latest")) + (with-image (xunil/alpine)) + (read :json) + next + dump)) diff --git a/go.mod b/go.mod index 01208ae0..74ff8f34 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,9 @@ require ( github.com/alecthomas/chroma v0.9.2 github.com/c-bata/go-prompt v0.2.6 github.com/cenkalti/backoff/v4 v4.1.2 - github.com/containerd/containerd v1.6.3-0.20220401172941-5ff8fce1fcc6 - github.com/docker/distribution v2.8.0+incompatible + github.com/containerd/containerd v1.6.6 + github.com/docker/distribution v2.8.1+incompatible + github.com/docker/docker v20.10.7+incompatible github.com/gertd/go-pluralize v0.1.7 github.com/gofrs/flock v0.8.1 github.com/google/go-cmp v0.5.7 @@ -19,8 +20,8 @@ require ( github.com/mattn/go-colorable v0.1.12 github.com/mattn/go-isatty v0.0.14 github.com/mattn/go-unicodeclass v0.0.1 - github.com/moby/buildkit v0.10.3 - github.com/moby/sys/mountinfo v0.6.0 + github.com/moby/buildkit v0.10.1-0.20220826012947-46c8b9ee45d0 + github.com/moby/sys/mountinfo v0.6.2 github.com/morikuni/aec v1.0.0 github.com/neovim/go-client v1.2.2-0.20220118223211-7c85d516f28c github.com/opencontainers/go-digest v1.0.0 @@ -33,6 +34,7 @@ require ( github.com/sourcegraph/jsonrpc2 v0.1.0 github.com/spf13/pflag v1.0.5 github.com/spy16/slurp v0.2.3 + github.com/square/certstrap v1.3.0 github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea github.com/vito/booklit v0.12.2-0.20220630023834-33787382be72 github.com/vito/go-interact v1.0.1 @@ -48,28 +50,28 @@ require ( golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 - google.golang.org/grpc v1.45.0 + google.golang.org/grpc v1.47.0 google.golang.org/protobuf v1.27.1 ) require ( cloud.google.com/go v0.81.0 // indirect + filippo.io/edwards25519 v1.0.0-rc.1 // indirect github.com/AdamKorcz/go-fuzz-headers v0.0.0-20210312213058-32f4d319f0d2 // indirect - github.com/Microsoft/go-winio v0.5.1 // indirect + github.com/Microsoft/go-winio v0.5.2 // indirect github.com/apex/log v1.4.0 // indirect github.com/charmbracelet/bubbles v0.13.0 // indirect github.com/charmbracelet/bubbletea v0.22.0 // indirect github.com/charmbracelet/lipgloss v0.5.0 // indirect github.com/containerd/console v1.0.3 // indirect - github.com/containerd/continuity v0.2.3-0.20220330195504-d132b287edc8 // indirect + github.com/containerd/continuity v0.3.0 // indirect github.com/containerd/go-runc v1.0.0 // indirect github.com/containerd/typeurl v1.0.2 // indirect github.com/creack/pty v1.1.11 // indirect github.com/cyphar/filepath-securejoin v0.2.3 // indirect github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect github.com/dlclark/regexp2 v1.4.0 // indirect - github.com/docker/cli v20.10.13+incompatible // indirect - github.com/docker/docker v20.10.7+incompatible // indirect + github.com/docker/cli v20.10.17+incompatible // indirect github.com/docker/docker-credential-helpers v0.6.4 // indirect github.com/fogleman/ease v0.0.0-20170301025033-8da417bf1776 // indirect github.com/go-bindata/go-bindata v3.1.2+incompatible // indirect @@ -85,7 +87,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/jessevdk/go-flags v1.4.0 // indirect - github.com/klauspost/compress v1.15.1 // indirect + github.com/klauspost/compress v1.15.7 // indirect github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/klauspost/pgzip v1.2.4 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect @@ -98,7 +100,7 @@ require ( github.com/muesli/cancelreader v0.2.1 // indirect github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 // indirect - github.com/opencontainers/runc v1.1.1 // indirect + github.com/opencontainers/runc v1.1.3 // indirect github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/term v1.2.0-beta.2 // indirect @@ -106,7 +108,7 @@ require ( github.com/rootless-containers/proto v0.1.0 // indirect github.com/sergi/go-diff v1.1.0 // indirect github.com/sirupsen/logrus v1.8.1 // indirect - github.com/tonistiigi/fsutil v0.0.0-20220115021204-b19f7f9cb274 // indirect + github.com/tonistiigi/fsutil v0.0.0-20220510150904-0dbf3a8a7d58 // indirect github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f // indirect github.com/vbatts/go-mtree v0.5.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0 // indirect @@ -114,6 +116,7 @@ require ( go.opentelemetry.io/otel/sdk v1.4.1 // indirect go.opentelemetry.io/otel/trace v1.4.1 // indirect go.opentelemetry.io/proto/otlp v0.12.0 // indirect + go.step.sm/crypto v0.16.2 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/goleak v1.1.12 // indirect go.uber.org/multierr v1.6.0 // indirect @@ -121,15 +124,15 @@ require ( golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect golang.org/x/text v0.3.7 // indirect - golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect + golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect golang.org/x/tools v0.1.10 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect + google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect ) // BEGIN SYNC buildkit -replace github.com/docker/docker => github.com/docker/docker v20.10.3-0.20220224222438-c78f6963a1c0+incompatible +replace github.com/docker/docker => github.com/docker/docker v20.10.3-0.20220414164044-61404de7df1a+incompatible // END SYNC diff --git a/go.sum b/go.sum index 88e07090..1b3a4eb9 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,4 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= -bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -39,13 +38,18 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= +filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= github.com/AdamKorcz/go-fuzz-headers v0.0.0-20210312213058-32f4d319f0d2 h1:dIxAd7URQa+ovSiQURY3UJu8Q7A2dG7QKTlxOlvDZHI= github.com/AdamKorcz/go-fuzz-headers v0.0.0-20210312213058-32f4d319f0d2/go.mod h1:VPevheIvXETHZT/ddjwarP3POR5p/cnH9Hy5yoFnQjc= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= -github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/hcsshim v0.9.2 h1:wB06W5aYFfUB3IvootYAY2WnOmIdgPGfqSI6tufQNnY= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= +github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/hcsshim v0.9.3 h1:k371PzBuRrz2b+ebGuI2nVgVhgsVX60jMfSw80NECxo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= @@ -105,19 +109,19 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.6.3-0.20220401172941-5ff8fce1fcc6 h1:nig7zto6cp3Wt1lPMK8EmyP6f/ZNmn/tL6ASQ7stews= -github.com/containerd/containerd v1.6.3-0.20220401172941-5ff8fce1fcc6/go.mod h1:WSt2SnDLAGWlu+Vl+EWay37seZLKqgRt6XLjIMy8SYM= +github.com/containerd/containerd v1.6.6 h1:xJNPhbrmz8xAMDNoVjHy9YHtWwEQNS+CDkcIRh7t8Y0= +github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0= github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= -github.com/containerd/continuity v0.2.3-0.20220330195504-d132b287edc8 h1:yGFEcFNMhze29DxAAB33v/1OMRYF/cM9iwwgV2P0ZrE= -github.com/containerd/continuity v0.2.3-0.20220330195504-d132b287edc8/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/containerd/fifo v1.0.0 h1:6PirWBr9/L7GDamKr+XM0IeUFXu5mf3M/BPpH9gaLBU= github.com/containerd/go-runc v1.0.0 h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0= github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= @@ -150,12 +154,12 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8 github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/docker/cli v20.10.13+incompatible h1:o/STAn7e+b/pQ6keReGRoewVmAgXUkZAMQ8st4vHdKg= -github.com/docker/cli v20.10.13+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v2.8.0+incompatible h1:l9EaZDICImO1ngI+uTifW+ZYvvz7fKISBAKpg+MbWbY= -github.com/docker/distribution v2.8.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.3-0.20220224222438-c78f6963a1c0+incompatible h1:Ptj2To+ezU/mCBUKdYXBQ2r3/2EJojAlOZrsgprF+is= -github.com/docker/docker v20.10.3-0.20220224222438-c78f6963a1c0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M= +github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v20.10.3-0.20220414164044-61404de7df1a+incompatible h1:jnhU41Zm9biz6e4GPOvAtuognZ+pi8S77ZlRir/SHRA= +github.com/docker/docker v20.10.3-0.20220414164044-61404de7df1a+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= @@ -168,8 +172,8 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= @@ -253,6 +257,7 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -276,6 +281,7 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= @@ -298,8 +304,13 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/in-toto/in-toto-golang v0.3.3 h1:tkkEBU5i09UEeWKnrp6Rq4fXKAfpVXYMLRO5mDfnb3I= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -315,8 +326,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A= -github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.7 h1:7cgTQxJCU/vy+oP/E3B9RGbQTgbiVzIJWIKOLoAsPok= +github.com/klauspost/compress v1.15.7/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/pgzip v1.2.4 h1:TQ7CNpYKovDOmqzRHKxJh0BeaBI7UdQZYc6p7pMQh1A= @@ -365,18 +376,22 @@ github.com/mattn/go-unicodeclass v0.0.1 h1:BKdh58FOa0n4QRd39jSeVEF7ncxxV3l4GL05L github.com/mattn/go-unicodeclass v0.0.1/go.mod h1:dDCkCgOKUwD3sYX4N+tVQdFh/xlFQ1+cWakbQzy98T8= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mna/pigeon v1.0.1-0.20200224192238-18953b277063 h1:V7s6vhIrNeOqocziAmRoVJh6gnPPx83ovlpT7Hf5shI= github.com/mna/pigeon v1.0.1-0.20200224192238-18953b277063/go.mod h1:rkFeDZ0gc+YbnrXPw0q2RlI0QRuKBBPu67fgYIyGRNg= -github.com/moby/buildkit v0.10.3 h1:/dGykD8FW+H4p++q5+KqKEo6gAkYKyBQHdawdjVwVAU= -github.com/moby/buildkit v0.10.3/go.mod h1:jxeOuly98l9gWHai0Ojrbnczrk/rf+o9/JqNhY+UCSo= +github.com/moby/buildkit v0.10.1-0.20220826012947-46c8b9ee45d0 h1:LCGBQM8P/GrQ41zFuLg10ey20n0ZEPquYBxZ/LkM09U= +github.com/moby/buildkit v0.10.1-0.20220826012947-46c8b9ee45d0/go.mod h1:g7HO1tvhm/frAzTc9tjPUPkQefHWxdGAqz2hscGrOyo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= -github.com/moby/sys/mountinfo v0.6.0 h1:gUDhXQx58YNrpHlK4nSL+7y2pxFZkUcXqzFDKWdC0Oo= -github.com/moby/sys/mountinfo v0.6.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= +github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/moby/sys/signal v0.6.0 h1:aDpY94H8VlhTGa9sNYUFCFsMZIUh5wm0B6XkIoJj/iY= github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= @@ -422,13 +437,13 @@ github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v1.0.0-rc90/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.1.1 h1:PJ9DSs2sVwE0iVr++pAHE6QkS9tzcVWozlPifdwMgrU= -github.com/opencontainers/runc v1.1.1/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= +github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w= +github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.10.0 h1:rAiKF8hTcgLI3w0DHm6i0ylVVcOrlgR1kK99DRLDhyU= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/opencontainers/selinux v1.10.1 h1:09LIPVRP3uuZGQvgR+SgMSNBd1Eb3vlRbGqQpoHsF8w= github.com/opencontainers/umoci v0.4.7 h1:mbIbtMpZ3v9oMpKaLopnWoLykgmnixeLzq51EzAX5nQ= github.com/opencontainers/umoci v0.4.7/go.mod h1:lgJ4bnwJezsN1o/5d7t/xdRPvmf8TvBko5kKYJsYvgo= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -469,12 +484,14 @@ github.com/rootless-containers/proto v0.1.0/go.mod h1:vgkUFZbQd0gcE/K/ZwtE4MYjZP github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= -github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/segmentio/textio v1.2.0 h1:Ug4IkV3kh72juJbG8azoSBlgebIbUUxVNrfFcKHfTSQ= github.com/segmentio/textio v1.2.0/go.mod h1:+Rb7v0YVODP+tK5F7FD9TCkV7gOYx9IgLHWiqtvY8ag= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shibumi/go-pathspec v1.2.0 h1:KVKEDHYk7bQolRMs7nfzjT3SBOCgcXFJzccnj9bsGbA= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -483,6 +500,8 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 h1:unQFBIznI+VYD1/1fApl1A+9VcBk+9dcqGfnePY87LY= +github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262/go.mod h1:MyOHs9Po2fbM1LHej6sBUT8ozbxmMOFG+E+rx/GSGuc= github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= @@ -492,6 +511,8 @@ github.com/sourcegraph/jsonrpc2 v0.1.0/go.mod h1:ZafdZgk/axhT1cvZAPOhw+95nz2I/Ra github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -500,6 +521,8 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spy16/slurp v0.2.3 h1:NZGZ3MEyd0IUlnauMiGcTJe0DfpE4BVe3SMfdFvdwNU= github.com/spy16/slurp v0.2.3/go.mod h1:Omrszh5Bznh+fhYrxnR4R2XrRKRelPlbY5IwQizOui0= +github.com/square/certstrap v1.3.0 h1:N9P0ZRA+DjT8pq5fGDj0z3FjafRKnBDypP0QHpMlaAk= +github.com/square/certstrap v1.3.0/go.mod h1:wGZo9eE1B7WX2GKBn0htJ+B3OuRl2UsdCFySNooy9hU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -517,13 +540,12 @@ github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eN github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tonistiigi/fsutil v0.0.0-20220115021204-b19f7f9cb274 h1:wbyZxD6IPFp0sl5uscMOJRsz5UKGFiNiD16e+MVfKZY= -github.com/tonistiigi/fsutil v0.0.0-20220115021204-b19f7f9cb274/go.mod h1:oPAfvw32vlUJSjyDcQ3Bu0nb2ON2B+G0dtVN/SZNJiA= +github.com/tonistiigi/fsutil v0.0.0-20220510150904-0dbf3a8a7d58 h1:rNya5ozLqz0lK46XhmsmqJuxmQLM8dAWabiT+5gZqLY= +github.com/tonistiigi/fsutil v0.0.0-20220510150904-0dbf3a8a7d58/go.mod h1:oPAfvw32vlUJSjyDcQ3Bu0nb2ON2B+G0dtVN/SZNJiA= github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0= github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk= github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f h1:DLpt6B5oaaS8jyXHa9VA4rrZloBVPVXeCtrOsrFauxc= github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc= -github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= @@ -581,6 +603,8 @@ go.opentelemetry.io/otel/trace v1.4.1/go.mod h1:iYEVbroFCNut9QkwEczV9vMRPHNKSSwY go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.12.0 h1:CMJ/3Wp7iOWES+CYLfnBv+DVmPbB+kmy9PJ92XvlR6c= go.opentelemetry.io/proto/otlp v0.12.0/go.mod h1:TsIjwGWIx5VFYv9KGVlOpxoBl5Dy+63SUguV7GGvlSQ= +go.step.sm/crypto v0.16.2 h1:Pr9aazTwWBBZNogUsOqhOrPSdwAa9pPs+lMB602lnDA= +go.step.sm/crypto v0.16.2/go.mod h1:1WkTOTY+fOX/RY4TnZREp6trQAsBHRQ7nu6QJBiNQF8= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -599,9 +623,11 @@ golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -683,6 +709,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -735,7 +763,6 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -778,6 +805,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -805,8 +833,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -937,8 +965,8 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa h1:I0YcKz0I7OAhddo7ya8kMnvprhcWM045PmkBdMO9zN0= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6 h1:FglFEfyj61zP3c6LgjmVHxYxZWXYul9oiS1EZqD5gLc= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -959,11 +987,10 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -988,6 +1015,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= @@ -1002,8 +1030,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/hack/test b/hack/test new file mode 100755 index 00000000..d63a39cb --- /dev/null +++ b/hack/test @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -e -u -x + +# for lsp tests, which have a submodule for lsp config +git submodule update --init --recursive + +if which gotestsum 2>&1 >/dev/null; then + # run tests + exec gotestsum -f dots -- "$@" +else + exec go test "$@" +fi diff --git a/nix/vendorSha256.txt b/nix/vendorSha256.txt index b8a223f8..a4e18484 100644 --- a/nix/vendorSha256.txt +++ b/nix/vendorSha256.txt @@ -1 +1 @@ -sha256-MsCqrSxISHbOKHTc1brHyInzu1KblwBVQ6rbHnTK4GA= +sha256-O41vov8FQLY0/mOR8Zdqmg7D2vWRgHfam/qkMSB8VF0= diff --git a/notes/v0.10.0.md b/notes/v0.10.0.md new file mode 100644 index 00000000..b871292c --- /dev/null +++ b/notes/v0.10.0.md @@ -0,0 +1,92 @@ +This is a big release that overhauls the networking stack and adds a new kind +of value: a *thunk addr*. + + +## thunk ports & addrs + +Thunks can now provide TCP ports using [`with-port`] which can be referenced +with [`addr`] to construct a [thunk addr]: + +```clojure +(def srv + (-> ($ python -m http.server "80") + (with-image (linux/python)) + (with-port :http 80))) + +(-> ($ wget (addr srv :http "http://$host:$port")) + (with-image (linux/alpine)) + run) +``` + +A thunk addr is a lot like a [thunk path] except it represents to a TCP address +instead of a filesystem path. + +When using a thunk addr you don't need to worry about managing the lifecycle of +the service that the thunk represents. The service will be run lazily, +de-duplicated across multiple Bass runs, and stopped when all clients go away. + +The advantage of this approach over traditional service lifecycle management +parallels the advantages of using thunk paths instead of managing state in a +local filesystem. It allows thunks that depend on services provided by other +thunks to remain reproducible, just like thunks that depend on files created by +other thunks. + +[`with-port`]: https://bass-lang.org/stdlib.html#binding-with-port +[`addr`]: https://bass-lang.org/stdlib.html#binding-addr +[thunk path]: https://bass-lang.org/bassics.html#term-thunk%20path +[thunk addr]: https://bass-lang.org/bassics.html#term-thunk%20addr + + +## bridge networking & DNS + +To prevent port collisions, thunks no longer run in the host network. Instead +they run in a [bridge network] where each thunk has its own IP and reaches +other thunks using DNS. + +Using DNS is important because IPs are not reproducible. If thunks reached each +other using direct container IPs then caches would be busted every time a +service runs. + +Now that thunks run in their own network, you can't use Bass to run and expose +services to the host machine. This may be added in a future release via port +forwarding. Alternatively you could take the `path-name` (a bit of a misnomer) +of the thunk and reverse-proxy to its container port using the same DNS server +that thunks use. + +[bridge network]: https://www.cni.dev/plugins/current/main/bridge/ +[`path-name`]: https://bass-lang.org/stdlib.html#binding-path-name + + +## automatic TLS + +Thunks may also use TLS. A unique "bass" certificate authority is generated by +the runtime and automaticaly trusted by all thunks that it runs. + +To generate a certificate for a thunk, use [`with-tls`]: + +```clojure +(def registry-mirror + (let [config {:version "0.1" + :http {:addr "0.0.0.0:5000" + :tls {:certificate "/registry.crt" + :key "/registry.key"}} + :storage {:filesystem {:rootdirectory "/var/lib/registry"}} + :proxy {:remoteurl "https://registry-1.docker.io"}}] + (-> ($ registry serve (mkfile ./config.yml (json config))) + (with-image (linux/registry)) + (with-tls /registry.crt /registry.key) + (with-port :http 5000)))) + +(defn main [] + (-> (from (linux/alpine) + ($ apk add curl) + ($ curl (addr registry-mirror :http "https://$host:$port/v2/"))) + run)) +``` + +Generating TLS certs is a necessary part of the puzzle because thunks use their +own hash as their hostname and DNS entry. It would be impossible to generate a +cert ahead of time and pass it to the thunk because doing so would change the +hash! + +[`with-tls`]: https://bass-lang.org/stdlib.html#binding-with-tls diff --git a/pkg/bass/encoding_test.go b/pkg/bass/encoding_test.go index 30fc670b..cf4cf9b1 100644 --- a/pkg/bass/encoding_test.go +++ b/pkg/bass/encoding_test.go @@ -126,6 +126,10 @@ var validThiccThunk = bass.Thunk{ {"http", 80}, {"ssh", 22}, }, + TLS: &bass.ThunkTLS{ + Cert: bass.FilePath{"cert"}, + Key: bass.FilePath{"key"}, + }, } var validThunkImages = []bass.ThunkImage{ diff --git a/pkg/bass/ground.go b/pkg/bass/ground.go index 2edea47f..e0d65762 100644 --- a/pkg/bass/ground.go +++ b/pkg/bass/ground.go @@ -696,6 +696,11 @@ func init() { `returns thunk with a named port appended to its ports`, `=> (with-port ($ godoc -http=:6060) :godoc 6060)`) + Ground.Set("with-tls", + Func("with-tls", "[thunk cert-path key-path]", (Thunk).WithTLS), + `returns thunk with paths to a TLS certificate and key to generate`, + `=> (with-tls ($ godoc -http=:6060) ./cert.pem ./key.pem)`) + Ground.Set("with-mount", Func("with-mount", "[thunk source target]", (Thunk).WithMount), `returns thunk with a mount from source to the target path`, diff --git a/pkg/bass/proto.go b/pkg/bass/proto.go index 63fc751a..9cfad56a 100644 --- a/pkg/bass/proto.go +++ b/pkg/bass/proto.go @@ -415,6 +415,23 @@ func (value Thunk) MarshalProto() (proto.Message, error) { }) } + if value.TLS != nil { + cert, err := value.TLS.Cert.MarshalProto() + if err != nil { + return nil, fmt.Errorf("marshal cert: %w", err) + } + + key, err := value.TLS.Key.MarshalProto() + if err != nil { + return nil, fmt.Errorf("marshal cert: %w", err) + } + + thunk.Tls = &proto.ThunkTLS{ + Cert: cert.(*proto.FilePath), + Key: key.(*proto.FilePath), + } + } + return thunk, nil } diff --git a/pkg/bass/thunk.go b/pkg/bass/thunk.go index efaf8ac8..825ae3c5 100644 --- a/pkg/bass/thunk.go +++ b/pkg/bass/thunk.go @@ -75,6 +75,9 @@ type Thunk struct { // thunk its embedded thunk will be started and all ports will be polled // until they are listening. Ports []ThunkPort `json:"ports,omitempty"` + + // TLS configures paths to place generated certificates. + TLS *ThunkTLS `json:"tls,omitempty"` } type ThunkPort struct { @@ -82,6 +85,11 @@ type ThunkPort struct { Port int `json:"port"` } +type ThunkTLS struct { + Cert FilePath `json:"cert"` + Key FilePath `json:"key"` +} + func (thunk *Thunk) UnmarshalProto(msg proto.Message) error { p, ok := msg.(*proto.Thunk) if !ok { @@ -172,6 +180,19 @@ func (thunk *Thunk) UnmarshalProto(msg proto.Message) error { } } + if p.Tls != nil { + thunk.TLS = &ThunkTLS{} + err := thunk.TLS.Cert.UnmarshalProto(p.Tls.Cert) + if err != nil { + return fmt.Errorf("unmarshal cert: %w", err) + } + + err = thunk.TLS.Key.UnmarshalProto(p.Tls.Key) + if err != nil { + return fmt.Errorf("unmarshal key: %w", err) + } + } + return nil } @@ -430,6 +451,15 @@ func (thunk Thunk) WithPort(name Symbol, port int) Thunk { return thunk } +// WithTLS configures the thunk with TLS. +func (thunk Thunk) WithTLS(cert, key FilePath) Thunk { + thunk.TLS = &ThunkTLS{ + Cert: cert, + Key: key, + } + return thunk +} + var _ Value = Thunk{} func (thunk Thunk) String() string { diff --git a/pkg/basstls/basstls.go b/pkg/basstls/basstls.go new file mode 100644 index 00000000..eccd149d --- /dev/null +++ b/pkg/basstls/basstls.go @@ -0,0 +1,187 @@ +package basstls + +import ( + "fmt" + "os" + "path/filepath" + "time" + + "github.com/adrg/xdg" + "github.com/gofrs/flock" + "github.com/square/certstrap/depot" + "github.com/square/certstrap/pkix" +) + +const ( + // Common name for the certificate authority. + CAName = "bass" + + // Arbitrary values for the CA cert. + CACountry = "CA" // Canada (coincidence) + CAProvince = "Ontario" + CALocality = "Toronto" + + // RSA key bits. + keySize = 2048 + + // File stored within the cert depot to synchronize cert generation. + lockFile = "certs.lock" +) + +var ( + // DefaultDir is the canonical location to store certs on the user's + // local machine. + DefaultDir = filepath.Join(xdg.ConfigHome, "bass", "tls") +) + +// CACert returns the path to the CA certificate in the given dir. +func CACert(dir string) string { + return filepath.Join(dir, CAName+".crt") +} + +func lockDepot(dir string) (*flock.Flock, error) { + lock := flock.New(filepath.Join(dir, lockFile)) + + if err := os.MkdirAll(dir, 0755); err != nil { + return nil, err + } + + if err := lock.Lock(); err != nil { + return nil, err + } + + return lock, nil +} + +// Init initializes dir with a CA. +func Init(dir string) error { + lock, err := lockDepot(dir) + if err != nil { + return err + } + + defer lock.Unlock() + + d, err := depot.NewFileDepot(dir) + if err != nil { + return fmt.Errorf("init depot: %w", err) + } + + _, err = depot.GetCertificate(d, CAName) + if err == nil { + // cert already exists + return nil + } + + key, err := pkix.CreateRSAKey(keySize) + if err != nil { + return fmt.Errorf("create key: %w", err) + } + + // TODO(vito): rotate rather than adding a ridiculous amount of time? + expiry := time.Now().AddDate(0, 0, 64) + + crt, err := pkix.CreateCertificateAuthority( + key, + "", + expiry, + "", + CACountry, + CAProvince, + CALocality, + CAName, + nil, + ) + if err != nil { + return fmt.Errorf("create ca: %w", err) + } + + err = depot.PutPrivateKey(d, CAName, key) + if err != nil { + return fmt.Errorf("put ca: %w", err) + } + + err = depot.PutCertificate(d, CAName, crt) + if err != nil { + return fmt.Errorf("put ca: %w", err) + } + + return lock.Unlock() +} + +func Generate(dir, host string) (*pkix.Certificate, *pkix.Key, error) { + lock, err := lockDepot(dir) + if err != nil { + return nil, nil, err + } + + defer lock.Unlock() + + d, err := depot.NewFileDepot(dir) + if err != nil { + return nil, nil, fmt.Errorf("init depot: %w", err) + } + + crt, err := depot.GetCertificate(d, host) + if err == nil { + // cert and key already exist + + key, err := depot.GetPrivateKey(d, host) + if err != nil { + return nil, nil, fmt.Errorf("get key: %w", err) + } + + return crt, key, nil + } + + caCrt, err := depot.GetCertificate(d, CAName) + if err != nil { + return nil, nil, fmt.Errorf("get cert: %w", err) + } + + caKey, err := depot.GetPrivateKey(d, CAName) + if err != nil { + return nil, nil, fmt.Errorf("get key: %w", err) + } + + key, err := pkix.CreateRSAKey(keySize) + if err != nil { + return nil, nil, fmt.Errorf("create key: %w", err) + } + + err = depot.PutPrivateKey(d, host, key) + if err != nil { + return nil, nil, fmt.Errorf("put cert: %w", err) + } + + csr, err := pkix.CreateCertificateSigningRequest( + key, + "", // Organizational Unit + nil, // IPs + []string{host}, // Domains + nil, // URLs + "", // Organization + CACountry, + CAProvince, + CALocality, + host, + ) + if err != nil { + return nil, nil, fmt.Errorf("create csr: %w", err) + } + + // TODO(vito): rotate rather than adding a ridiculous amount of time? + expiry := time.Now().AddDate(0, 0, 64) + + crt, err = pkix.CreateCertificateHost(caCrt, caKey, csr, expiry) + if err != nil { + return nil, nil, fmt.Errorf("create cert: %w", err) + } + + err = depot.PutCertificate(d, host, crt) + if err != nil { + return nil, nil, fmt.Errorf("put cert: %w", err) + } + + return crt, key, nil +} diff --git a/pkg/proto/bass.pb.go b/pkg/proto/bass.pb.go index 68c448eb..575095eb 100644 --- a/pkg/proto/bass.pb.go +++ b/pkg/proto/bass.pb.go @@ -297,6 +297,7 @@ type Thunk struct { 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"` } func (x *Thunk) Reset() { @@ -401,6 +402,13 @@ func (x *Thunk) GetPorts() []*ThunkPort { return nil } +func (x *Thunk) GetTls() *ThunkTLS { + if x != nil { + return x.Tls + } + return nil +} + type ThunkAddr struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -519,6 +527,61 @@ func (x *ThunkPort) GetPort() int32 { return 0 } +type ThunkTLS struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cert *FilePath `protobuf:"bytes,1,opt,name=cert,proto3" json:"cert,omitempty"` + Key *FilePath `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` +} + +func (x *ThunkTLS) Reset() { + *x = ThunkTLS{} + if protoimpl.UnsafeEnabled { + mi := &file_bass_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ThunkTLS) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ThunkTLS) ProtoMessage() {} + +func (x *ThunkTLS) ProtoReflect() protoreflect.Message { + mi := &file_bass_proto_msgTypes[4] + 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 ThunkTLS.ProtoReflect.Descriptor instead. +func (*ThunkTLS) Descriptor() ([]byte, []int) { + return file_bass_proto_rawDescGZIP(), []int{4} +} + +func (x *ThunkTLS) GetCert() *FilePath { + if x != nil { + return x.Cert + } + return nil +} + +func (x *ThunkTLS) GetKey() *FilePath { + if x != nil { + return x.Key + } + return nil +} + type ThunkImage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -534,7 +597,7 @@ type ThunkImage struct { func (x *ThunkImage) Reset() { *x = ThunkImage{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[4] + mi := &file_bass_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -547,7 +610,7 @@ func (x *ThunkImage) String() string { func (*ThunkImage) ProtoMessage() {} func (x *ThunkImage) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[4] + mi := &file_bass_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -560,7 +623,7 @@ func (x *ThunkImage) ProtoReflect() protoreflect.Message { // Deprecated: Use ThunkImage.ProtoReflect.Descriptor instead. func (*ThunkImage) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{4} + return file_bass_proto_rawDescGZIP(), []int{5} } func (m *ThunkImage) GetImage() isThunkImage_Image { @@ -631,7 +694,7 @@ type ImageRef struct { func (x *ImageRef) Reset() { *x = ImageRef{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[5] + mi := &file_bass_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -644,7 +707,7 @@ func (x *ImageRef) String() string { func (*ImageRef) ProtoMessage() {} func (x *ImageRef) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[5] + mi := &file_bass_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -657,7 +720,7 @@ func (x *ImageRef) ProtoReflect() protoreflect.Message { // Deprecated: Use ImageRef.ProtoReflect.Descriptor instead. func (*ImageRef) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{5} + return file_bass_proto_rawDescGZIP(), []int{6} } func (m *ImageRef) GetSource() isImageRef_Source { @@ -746,7 +809,7 @@ type ImageArchive struct { func (x *ImageArchive) Reset() { *x = ImageArchive{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[6] + mi := &file_bass_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -759,7 +822,7 @@ func (x *ImageArchive) String() string { func (*ImageArchive) ProtoMessage() {} func (x *ImageArchive) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[6] + mi := &file_bass_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -772,7 +835,7 @@ func (x *ImageArchive) ProtoReflect() protoreflect.Message { // Deprecated: Use ImageArchive.ProtoReflect.Descriptor instead. func (*ImageArchive) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{6} + return file_bass_proto_rawDescGZIP(), []int{7} } func (x *ImageArchive) GetFile() *ThunkPath { @@ -808,7 +871,7 @@ type Platform struct { func (x *Platform) Reset() { *x = Platform{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[7] + mi := &file_bass_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -821,7 +884,7 @@ func (x *Platform) String() string { func (*Platform) ProtoMessage() {} func (x *Platform) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[7] + mi := &file_bass_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -834,7 +897,7 @@ func (x *Platform) ProtoReflect() protoreflect.Message { // Deprecated: Use Platform.ProtoReflect.Descriptor instead. func (*Platform) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{7} + return file_bass_proto_rawDescGZIP(), []int{8} } func (x *Platform) GetOs() string { @@ -869,7 +932,7 @@ type ThunkCmd struct { func (x *ThunkCmd) Reset() { *x = ThunkCmd{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[8] + mi := &file_bass_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -882,7 +945,7 @@ func (x *ThunkCmd) String() string { func (*ThunkCmd) ProtoMessage() {} func (x *ThunkCmd) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[8] + mi := &file_bass_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -895,7 +958,7 @@ func (x *ThunkCmd) ProtoReflect() protoreflect.Message { // Deprecated: Use ThunkCmd.ProtoReflect.Descriptor instead. func (*ThunkCmd) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{8} + return file_bass_proto_rawDescGZIP(), []int{9} } func (m *ThunkCmd) GetCmd() isThunkCmd_Cmd { @@ -1002,7 +1065,7 @@ type ThunkDir struct { func (x *ThunkDir) Reset() { *x = ThunkDir{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[9] + mi := &file_bass_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1015,7 +1078,7 @@ func (x *ThunkDir) String() string { func (*ThunkDir) ProtoMessage() {} func (x *ThunkDir) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[9] + mi := &file_bass_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1028,7 +1091,7 @@ func (x *ThunkDir) ProtoReflect() protoreflect.Message { // Deprecated: Use ThunkDir.ProtoReflect.Descriptor instead. func (*ThunkDir) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{9} + return file_bass_proto_rawDescGZIP(), []int{10} } func (m *ThunkDir) GetDir() isThunkDir_Dir { @@ -1098,7 +1161,7 @@ type ThunkMountSource struct { func (x *ThunkMountSource) Reset() { *x = ThunkMountSource{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[10] + mi := &file_bass_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1111,7 +1174,7 @@ func (x *ThunkMountSource) String() string { func (*ThunkMountSource) ProtoMessage() {} func (x *ThunkMountSource) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[10] + mi := &file_bass_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1124,7 +1187,7 @@ func (x *ThunkMountSource) ProtoReflect() protoreflect.Message { // Deprecated: Use ThunkMountSource.ProtoReflect.Descriptor instead. func (*ThunkMountSource) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{10} + return file_bass_proto_rawDescGZIP(), []int{11} } func (m *ThunkMountSource) GetSource() isThunkMountSource_Source { @@ -1215,7 +1278,7 @@ type ThunkMount struct { func (x *ThunkMount) Reset() { *x = ThunkMount{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[11] + mi := &file_bass_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1228,7 +1291,7 @@ func (x *ThunkMount) String() string { func (*ThunkMount) ProtoMessage() {} func (x *ThunkMount) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[11] + mi := &file_bass_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1241,7 +1304,7 @@ func (x *ThunkMount) ProtoReflect() protoreflect.Message { // Deprecated: Use ThunkMount.ProtoReflect.Descriptor instead. func (*ThunkMount) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{11} + return file_bass_proto_rawDescGZIP(), []int{12} } func (x *ThunkMount) GetSource() *ThunkMountSource { @@ -1269,7 +1332,7 @@ type Array struct { func (x *Array) Reset() { *x = Array{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[12] + mi := &file_bass_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1282,7 +1345,7 @@ func (x *Array) String() string { func (*Array) ProtoMessage() {} func (x *Array) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[12] + mi := &file_bass_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1295,7 +1358,7 @@ func (x *Array) ProtoReflect() protoreflect.Message { // Deprecated: Use Array.ProtoReflect.Descriptor instead. func (*Array) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{12} + return file_bass_proto_rawDescGZIP(), []int{13} } func (x *Array) GetValues() []*Value { @@ -1316,7 +1379,7 @@ type Object struct { func (x *Object) Reset() { *x = Object{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[13] + mi := &file_bass_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1329,7 +1392,7 @@ func (x *Object) String() string { func (*Object) ProtoMessage() {} func (x *Object) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[13] + mi := &file_bass_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1342,7 +1405,7 @@ func (x *Object) ProtoReflect() protoreflect.Message { // Deprecated: Use Object.ProtoReflect.Descriptor instead. func (*Object) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{13} + return file_bass_proto_rawDescGZIP(), []int{14} } func (x *Object) GetBindings() []*Binding { @@ -1364,7 +1427,7 @@ type Binding struct { func (x *Binding) Reset() { *x = Binding{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[14] + mi := &file_bass_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1377,7 +1440,7 @@ func (x *Binding) String() string { func (*Binding) ProtoMessage() {} func (x *Binding) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[14] + mi := &file_bass_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1390,7 +1453,7 @@ func (x *Binding) ProtoReflect() protoreflect.Message { // Deprecated: Use Binding.ProtoReflect.Descriptor instead. func (*Binding) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{14} + return file_bass_proto_rawDescGZIP(), []int{15} } func (x *Binding) GetSymbol() string { @@ -1416,7 +1479,7 @@ type Null struct { func (x *Null) Reset() { *x = Null{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[15] + mi := &file_bass_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1429,7 +1492,7 @@ func (x *Null) String() string { func (*Null) ProtoMessage() {} func (x *Null) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[15] + mi := &file_bass_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1442,7 +1505,7 @@ func (x *Null) ProtoReflect() protoreflect.Message { // Deprecated: Use Null.ProtoReflect.Descriptor instead. func (*Null) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{15} + return file_bass_proto_rawDescGZIP(), []int{16} } type Bool struct { @@ -1456,7 +1519,7 @@ type Bool struct { func (x *Bool) Reset() { *x = Bool{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[16] + mi := &file_bass_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1469,7 +1532,7 @@ func (x *Bool) String() string { func (*Bool) ProtoMessage() {} func (x *Bool) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[16] + mi := &file_bass_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1482,7 +1545,7 @@ func (x *Bool) ProtoReflect() protoreflect.Message { // Deprecated: Use Bool.ProtoReflect.Descriptor instead. func (*Bool) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{16} + return file_bass_proto_rawDescGZIP(), []int{17} } func (x *Bool) GetValue() bool { @@ -1503,7 +1566,7 @@ type Int struct { func (x *Int) Reset() { *x = Int{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[17] + mi := &file_bass_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1516,7 +1579,7 @@ func (x *Int) String() string { func (*Int) ProtoMessage() {} func (x *Int) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[17] + mi := &file_bass_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1529,7 +1592,7 @@ func (x *Int) ProtoReflect() protoreflect.Message { // Deprecated: Use Int.ProtoReflect.Descriptor instead. func (*Int) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{17} + return file_bass_proto_rawDescGZIP(), []int{18} } func (x *Int) GetValue() int64 { @@ -1550,7 +1613,7 @@ type String struct { func (x *String) Reset() { *x = String{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[18] + mi := &file_bass_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1563,7 +1626,7 @@ func (x *String) String() string { func (*String) ProtoMessage() {} func (x *String) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[18] + mi := &file_bass_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1576,7 +1639,7 @@ func (x *String) ProtoReflect() protoreflect.Message { // Deprecated: Use String.ProtoReflect.Descriptor instead. func (*String) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{18} + return file_bass_proto_rawDescGZIP(), []int{19} } func (x *String) GetValue() string { @@ -1598,7 +1661,7 @@ type CachePath struct { func (x *CachePath) Reset() { *x = CachePath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[19] + mi := &file_bass_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1611,7 +1674,7 @@ func (x *CachePath) String() string { func (*CachePath) ProtoMessage() {} func (x *CachePath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[19] + mi := &file_bass_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1624,7 +1687,7 @@ func (x *CachePath) ProtoReflect() protoreflect.Message { // Deprecated: Use CachePath.ProtoReflect.Descriptor instead. func (*CachePath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{19} + return file_bass_proto_rawDescGZIP(), []int{20} } func (x *CachePath) GetId() string { @@ -1652,7 +1715,7 @@ type Secret struct { func (x *Secret) Reset() { *x = Secret{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[20] + mi := &file_bass_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1665,7 +1728,7 @@ func (x *Secret) String() string { func (*Secret) ProtoMessage() {} func (x *Secret) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[20] + mi := &file_bass_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1678,7 +1741,7 @@ func (x *Secret) ProtoReflect() protoreflect.Message { // Deprecated: Use Secret.ProtoReflect.Descriptor instead. func (*Secret) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{20} + return file_bass_proto_rawDescGZIP(), []int{21} } func (x *Secret) GetName() string { @@ -1699,7 +1762,7 @@ type CommandPath struct { func (x *CommandPath) Reset() { *x = CommandPath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[21] + mi := &file_bass_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1712,7 +1775,7 @@ func (x *CommandPath) String() string { func (*CommandPath) ProtoMessage() {} func (x *CommandPath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[21] + mi := &file_bass_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1725,7 +1788,7 @@ func (x *CommandPath) ProtoReflect() protoreflect.Message { // Deprecated: Use CommandPath.ProtoReflect.Descriptor instead. func (*CommandPath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{21} + return file_bass_proto_rawDescGZIP(), []int{22} } func (x *CommandPath) GetName() string { @@ -1746,7 +1809,7 @@ type FilePath struct { func (x *FilePath) Reset() { *x = FilePath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[22] + mi := &file_bass_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1759,7 +1822,7 @@ func (x *FilePath) String() string { func (*FilePath) ProtoMessage() {} func (x *FilePath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[22] + mi := &file_bass_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1772,7 +1835,7 @@ func (x *FilePath) ProtoReflect() protoreflect.Message { // Deprecated: Use FilePath.ProtoReflect.Descriptor instead. func (*FilePath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{22} + return file_bass_proto_rawDescGZIP(), []int{23} } func (x *FilePath) GetPath() string { @@ -1793,7 +1856,7 @@ type DirPath struct { func (x *DirPath) Reset() { *x = DirPath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[23] + mi := &file_bass_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1806,7 +1869,7 @@ func (x *DirPath) String() string { func (*DirPath) ProtoMessage() {} func (x *DirPath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[23] + mi := &file_bass_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1819,7 +1882,7 @@ func (x *DirPath) ProtoReflect() protoreflect.Message { // Deprecated: Use DirPath.ProtoReflect.Descriptor instead. func (*DirPath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{23} + return file_bass_proto_rawDescGZIP(), []int{24} } func (x *DirPath) GetPath() string { @@ -1843,7 +1906,7 @@ type FilesystemPath struct { func (x *FilesystemPath) Reset() { *x = FilesystemPath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[24] + mi := &file_bass_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1856,7 +1919,7 @@ func (x *FilesystemPath) String() string { func (*FilesystemPath) ProtoMessage() {} func (x *FilesystemPath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[24] + mi := &file_bass_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1869,7 +1932,7 @@ func (x *FilesystemPath) ProtoReflect() protoreflect.Message { // Deprecated: Use FilesystemPath.ProtoReflect.Descriptor instead. func (*FilesystemPath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{24} + return file_bass_proto_rawDescGZIP(), []int{25} } func (m *FilesystemPath) GetPath() isFilesystemPath_Path { @@ -1921,7 +1984,7 @@ type ThunkPath struct { func (x *ThunkPath) Reset() { *x = ThunkPath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[25] + mi := &file_bass_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1934,7 +1997,7 @@ func (x *ThunkPath) String() string { func (*ThunkPath) ProtoMessage() {} func (x *ThunkPath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[25] + mi := &file_bass_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1947,7 +2010,7 @@ func (x *ThunkPath) ProtoReflect() protoreflect.Message { // Deprecated: Use ThunkPath.ProtoReflect.Descriptor instead. func (*ThunkPath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{25} + return file_bass_proto_rawDescGZIP(), []int{26} } func (x *ThunkPath) GetThunk() *Thunk { @@ -1976,7 +2039,7 @@ type HostPath struct { func (x *HostPath) Reset() { *x = HostPath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[26] + mi := &file_bass_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1989,7 +2052,7 @@ func (x *HostPath) String() string { func (*HostPath) ProtoMessage() {} func (x *HostPath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[26] + mi := &file_bass_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2002,7 +2065,7 @@ func (x *HostPath) ProtoReflect() protoreflect.Message { // Deprecated: Use HostPath.ProtoReflect.Descriptor instead. func (*HostPath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{26} + return file_bass_proto_rawDescGZIP(), []int{27} } func (x *HostPath) GetContext() string { @@ -2033,7 +2096,7 @@ type LogicalPath struct { func (x *LogicalPath) Reset() { *x = LogicalPath{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[27] + mi := &file_bass_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2046,7 +2109,7 @@ func (x *LogicalPath) String() string { func (*LogicalPath) ProtoMessage() {} func (x *LogicalPath) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[27] + mi := &file_bass_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2059,7 +2122,7 @@ func (x *LogicalPath) ProtoReflect() protoreflect.Message { // Deprecated: Use LogicalPath.ProtoReflect.Descriptor instead. func (*LogicalPath) Descriptor() ([]byte, []int) { - return file_bass_proto_rawDescGZIP(), []int{27} + return file_bass_proto_rawDescGZIP(), []int{28} } func (m *LogicalPath) GetPath() isLogicalPath_Path { @@ -2111,7 +2174,7 @@ type LogicalPath_File struct { func (x *LogicalPath_File) Reset() { *x = LogicalPath_File{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[28] + mi := &file_bass_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2124,7 +2187,7 @@ func (x *LogicalPath_File) String() string { func (*LogicalPath_File) ProtoMessage() {} func (x *LogicalPath_File) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[28] + mi := &file_bass_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2137,7 +2200,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{27, 0} + return file_bass_proto_rawDescGZIP(), []int{28, 0} } func (x *LogicalPath_File) GetName() string { @@ -2166,7 +2229,7 @@ type LogicalPath_Dir struct { func (x *LogicalPath_Dir) Reset() { *x = LogicalPath_Dir{} if protoimpl.UnsafeEnabled { - mi := &file_bass_proto_msgTypes[29] + mi := &file_bass_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2179,7 +2242,7 @@ func (x *LogicalPath_Dir) String() string { func (*LogicalPath_Dir) ProtoMessage() {} func (x *LogicalPath_Dir) ProtoReflect() protoreflect.Message { - mi := &file_bass_proto_msgTypes[29] + mi := &file_bass_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2192,7 +2255,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{27, 1} + return file_bass_proto_rawDescGZIP(), []int{28, 1} } func (x *LogicalPath_Dir) GetName() string { @@ -2254,7 +2317,7 @@ var file_bass_proto_rawDesc = []byte{ 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, 0xec, 0x02, 0x0a, 0x05, 0x54, 0x68, 0x75, + 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, @@ -2277,161 +2340,169 @@ var file_bass_proto_rawDesc = []byte{ 0x2e, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x25, 0x0a, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x6f, 0x72, 0x74, - 0x52, 0x05, 0x70, 0x6f, 0x72, 0x74, 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, 0x8e, 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, - 0x42, 0x07, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0xfb, 0x01, 0x0a, 0x08, 0x49, 0x6d, - 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, 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, 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, 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, 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, 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, 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, 0x2e, 0x0a, 0x08, 0x50, 0x6c, 0x61, 0x74, 0x66, - 0x6f, 0x72, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x6f, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x22, 0x8d, 0x02, 0x0a, 0x08, 0x54, 0x68, 0x75, 0x6e, - 0x6b, 0x43, 0x6d, 0x64, 0x12, 0x2d, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x43, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x12, 0x24, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, - 0x68, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x27, 0x0a, 0x05, 0x74, 0x68, 0x75, - 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, - 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x74, 0x68, 0x75, - 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, - 0x48, 0x00, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x07, 0x6c, 0x6f, 0x67, 0x69, - 0x63, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x61, 0x73, 0x73, - 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x07, - 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x05, 0x63, 0x61, 0x63, 0x68, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x43, 0x61, - 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x63, 0x61, 0x63, 0x68, 0x65, - 0x42, 0x05, 0x0a, 0x03, 0x63, 0x6d, 0x64, 0x22, 0x87, 0x01, 0x0a, 0x08, 0x54, 0x68, 0x75, 0x6e, - 0x6b, 0x44, 0x69, 0x72, 0x12, 0x25, 0x0a, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x0c, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x44, 0x69, 0x72, 0x50, 0x61, - 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x05, 0x74, - 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, - 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x74, - 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x61, - 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x42, 0x05, 0x0a, 0x03, 0x64, 0x69, - 0x72, 0x22, 0xeb, 0x01, 0x0a, 0x10, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x6f, 0x75, 0x6e, 0x74, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, - 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, - 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, - 0x62, 0x61, 0x73, 0x73, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, - 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x07, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, - 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x07, 0x6c, 0x6f, 0x67, - 0x69, 0x63, 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x05, 0x63, 0x61, 0x63, 0x68, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, - 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x63, 0x61, 0x63, 0x68, 0x65, 0x12, 0x26, 0x0a, - 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, - 0x62, 0x61, 0x73, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x48, 0x00, 0x52, 0x06, 0x73, - 0x65, 0x63, 0x72, 0x65, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, - 0x6a, 0x0a, 0x0a, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, 0x0a, - 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, - 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2c, 0x0a, - 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, - 0x61, 0x74, 0x68, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x2c, 0x0a, 0x05, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x12, 0x23, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x33, 0x0a, 0x06, 0x4f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x12, 0x29, 0x0a, 0x08, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x42, 0x69, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x44, - 0x0a, 0x07, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6d, - 0x62, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x79, 0x6d, 0x62, 0x6f, - 0x6c, 0x12, 0x21, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0x06, 0x0a, 0x04, 0x4e, 0x75, 0x6c, 0x6c, 0x22, 0x1c, 0x0a, 0x04, - 0x42, 0x6f, 0x6f, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1b, 0x0a, 0x03, 0x49, 0x6e, - 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1e, 0x0a, 0x06, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x45, 0x0a, 0x09, 0x43, 0x61, 0x63, 0x68, 0x65, - 0x50, 0x61, 0x74, 0x68, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x1c, - 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x21, 0x0a, 0x0b, - 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, - 0x1e, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x70, - 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, - 0x1d, 0x0a, 0x07, 0x44, 0x69, 0x72, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x61, - 0x0a, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, - 0x12, 0x24, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, - 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, - 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x03, 0x64, 0x69, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x44, 0x69, 0x72, 0x50, 0x61, - 0x74, 0x68, 0x48, 0x00, 0x52, 0x03, 0x64, 0x69, 0x72, 0x42, 0x06, 0x0a, 0x04, 0x70, 0x61, 0x74, - 0x68, 0x22, 0x58, 0x0a, 0x09, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x12, 0x21, - 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, - 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, - 0x6b, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x4e, 0x0a, 0x08, 0x48, - 0x6f, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0xec, 0x01, 0x0a, 0x0b, - 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x2c, 0x0a, 0x04, 0x66, - 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x61, 0x73, 0x73, - 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x2e, 0x46, 0x69, 0x6c, - 0x65, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x29, 0x0a, 0x03, 0x64, 0x69, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, - 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x2e, 0x44, 0x69, 0x72, 0x48, 0x00, 0x52, - 0x03, 0x64, 0x69, 0x72, 0x1a, 0x34, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, + 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, 0x8e, 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, 0x42, 0x07, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0xfb, 0x01, + 0x0a, 0x08, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, 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, 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, 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, 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, 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, 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, 0x2e, 0x0a, 0x08, 0x50, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x6f, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x22, 0x8d, 0x02, 0x0a, 0x08, + 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x43, 0x6d, 0x64, 0x12, 0x2d, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x61, 0x73, 0x73, + 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x07, + 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x24, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, + 0x65, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x27, 0x0a, + 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, + 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, + 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x48, 0x6f, 0x73, 0x74, + 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x07, + 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, + 0x48, 0x00, 0x52, 0x07, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x05, 0x63, + 0x61, 0x63, 0x68, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, + 0x73, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x63, + 0x61, 0x63, 0x68, 0x65, 0x42, 0x05, 0x0a, 0x03, 0x63, 0x6d, 0x64, 0x22, 0x87, 0x01, 0x0a, 0x08, + 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x44, 0x69, 0x72, 0x12, 0x25, 0x0a, 0x05, 0x6c, 0x6f, 0x63, 0x61, + 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x44, + 0x69, 0x72, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x12, + 0x27, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, + 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, + 0x00, 0x52, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, + 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x48, 0x6f, + 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x42, 0x05, + 0x0a, 0x03, 0x64, 0x69, 0x72, 0x22, 0xeb, 0x01, 0x0a, 0x10, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, + 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x05, 0x74, 0x68, + 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, + 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x74, 0x68, + 0x75, 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x61, 0x74, + 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x07, 0x6c, 0x6f, 0x67, + 0x69, 0x63, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x61, 0x73, + 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, + 0x07, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x05, 0x63, 0x61, 0x63, 0x68, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x43, + 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x05, 0x63, 0x61, 0x63, 0x68, + 0x65, 0x12, 0x26, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0c, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x48, + 0x00, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x22, 0x6a, 0x0a, 0x0a, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x6f, + 0x75, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, + 0x2c, 0x0a, 0x05, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x23, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x33, 0x0a, + 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x29, 0x0a, 0x08, 0x62, 0x69, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, + 0x2e, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, + 0x67, 0x73, 0x22, 0x44, 0x0a, 0x07, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x16, 0x0a, + 0x06, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, + 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x12, 0x21, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x06, 0x0a, 0x04, 0x4e, 0x75, 0x6c, 0x6c, + 0x22, 0x1c, 0x0a, 0x04, 0x42, 0x6f, 0x6f, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1b, + 0x0a, 0x03, 0x49, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1e, 0x0a, 0x06, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x45, 0x0a, 0x09, 0x43, + 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, + 0x74, 0x68, 0x22, 0x1c, 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 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, + 0x22, 0x21, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x22, 0x1e, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, + 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, + 0x61, 0x74, 0x68, 0x22, 0x1d, 0x0a, 0x07, 0x44, 0x69, 0x72, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, + 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, + 0x74, 0x68, 0x22, 0x61, 0x0a, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, + 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x03, 0x64, 0x69, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x44, + 0x69, 0x72, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x03, 0x64, 0x69, 0x72, 0x42, 0x06, 0x0a, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x58, 0x0a, 0x09, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x61, + 0x74, 0x68, 0x12, 0x21, 0x0a, 0x05, 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x54, 0x68, 0x75, 0x6e, 0x6b, 0x52, 0x05, + 0x74, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, + 0x4e, 0x0a, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x61, 0x73, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, + 0xec, 0x01, 0x0a, 0x0b, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, + 0x2c, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x62, 0x61, 0x73, 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, + 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x29, 0x0a, + 0x03, 0x64, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x62, 0x61, 0x73, + 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x2e, 0x44, 0x69, + 0x72, 0x48, 0x00, 0x52, 0x03, 0x64, 0x69, 0x72, 0x1a, 0x34, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x1a, 0x46, + 0x0a, 0x03, 0x44, 0x69, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x07, 0x65, 0x6e, 0x74, + 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x61, 0x73, + 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x52, 0x07, 0x65, + 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x42, 0x0b, + 0x5a, 0x09, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -2446,106 +2517,110 @@ func file_bass_proto_rawDescGZIP() []byte { return file_bass_proto_rawDescData } -var file_bass_proto_msgTypes = make([]protoimpl.MessageInfo, 30) +var file_bass_proto_msgTypes = make([]protoimpl.MessageInfo, 31) var file_bass_proto_goTypes = []interface{}{ (*Value)(nil), // 0: bass.Value (*Thunk)(nil), // 1: bass.Thunk (*ThunkAddr)(nil), // 2: bass.ThunkAddr (*ThunkPort)(nil), // 3: bass.ThunkPort - (*ThunkImage)(nil), // 4: bass.ThunkImage - (*ImageRef)(nil), // 5: bass.ImageRef - (*ImageArchive)(nil), // 6: bass.ImageArchive - (*Platform)(nil), // 7: bass.Platform - (*ThunkCmd)(nil), // 8: bass.ThunkCmd - (*ThunkDir)(nil), // 9: bass.ThunkDir - (*ThunkMountSource)(nil), // 10: bass.ThunkMountSource - (*ThunkMount)(nil), // 11: bass.ThunkMount - (*Array)(nil), // 12: bass.Array - (*Object)(nil), // 13: bass.Object - (*Binding)(nil), // 14: bass.Binding - (*Null)(nil), // 15: bass.Null - (*Bool)(nil), // 16: bass.Bool - (*Int)(nil), // 17: bass.Int - (*String)(nil), // 18: bass.String - (*CachePath)(nil), // 19: bass.CachePath - (*Secret)(nil), // 20: bass.Secret - (*CommandPath)(nil), // 21: bass.CommandPath - (*FilePath)(nil), // 22: bass.FilePath - (*DirPath)(nil), // 23: bass.DirPath - (*FilesystemPath)(nil), // 24: bass.FilesystemPath - (*ThunkPath)(nil), // 25: bass.ThunkPath - (*HostPath)(nil), // 26: bass.HostPath - (*LogicalPath)(nil), // 27: bass.LogicalPath - (*LogicalPath_File)(nil), // 28: bass.LogicalPath.File - (*LogicalPath_Dir)(nil), // 29: bass.LogicalPath.Dir + (*ThunkTLS)(nil), // 4: bass.ThunkTLS + (*ThunkImage)(nil), // 5: bass.ThunkImage + (*ImageRef)(nil), // 6: bass.ImageRef + (*ImageArchive)(nil), // 7: bass.ImageArchive + (*Platform)(nil), // 8: bass.Platform + (*ThunkCmd)(nil), // 9: bass.ThunkCmd + (*ThunkDir)(nil), // 10: bass.ThunkDir + (*ThunkMountSource)(nil), // 11: bass.ThunkMountSource + (*ThunkMount)(nil), // 12: bass.ThunkMount + (*Array)(nil), // 13: bass.Array + (*Object)(nil), // 14: bass.Object + (*Binding)(nil), // 15: bass.Binding + (*Null)(nil), // 16: bass.Null + (*Bool)(nil), // 17: bass.Bool + (*Int)(nil), // 18: bass.Int + (*String)(nil), // 19: bass.String + (*CachePath)(nil), // 20: bass.CachePath + (*Secret)(nil), // 21: bass.Secret + (*CommandPath)(nil), // 22: bass.CommandPath + (*FilePath)(nil), // 23: bass.FilePath + (*DirPath)(nil), // 24: bass.DirPath + (*FilesystemPath)(nil), // 25: bass.FilesystemPath + (*ThunkPath)(nil), // 26: bass.ThunkPath + (*HostPath)(nil), // 27: bass.HostPath + (*LogicalPath)(nil), // 28: bass.LogicalPath + (*LogicalPath_File)(nil), // 29: bass.LogicalPath.File + (*LogicalPath_Dir)(nil), // 30: bass.LogicalPath.Dir } var file_bass_proto_depIdxs = []int32{ - 15, // 0: bass.Value.null:type_name -> bass.Null - 16, // 1: bass.Value.bool:type_name -> bass.Bool - 17, // 2: bass.Value.int:type_name -> bass.Int - 18, // 3: bass.Value.string:type_name -> bass.String - 20, // 4: bass.Value.secret:type_name -> bass.Secret - 12, // 5: bass.Value.array:type_name -> bass.Array - 13, // 6: bass.Value.object:type_name -> bass.Object + 16, // 0: bass.Value.null:type_name -> bass.Null + 17, // 1: bass.Value.bool:type_name -> bass.Bool + 18, // 2: bass.Value.int:type_name -> bass.Int + 19, // 3: bass.Value.string:type_name -> bass.String + 21, // 4: bass.Value.secret:type_name -> bass.Secret + 13, // 5: bass.Value.array:type_name -> bass.Array + 14, // 6: bass.Value.object:type_name -> bass.Object 1, // 7: bass.Value.thunk:type_name -> bass.Thunk - 21, // 8: bass.Value.command_path:type_name -> bass.CommandPath - 22, // 9: bass.Value.file_path:type_name -> bass.FilePath - 23, // 10: bass.Value.dir_path:type_name -> bass.DirPath - 26, // 11: bass.Value.host_path:type_name -> bass.HostPath - 25, // 12: bass.Value.thunk_path:type_name -> bass.ThunkPath - 27, // 13: bass.Value.logical_path:type_name -> bass.LogicalPath + 22, // 8: bass.Value.command_path:type_name -> bass.CommandPath + 23, // 9: bass.Value.file_path:type_name -> bass.FilePath + 24, // 10: bass.Value.dir_path:type_name -> bass.DirPath + 27, // 11: bass.Value.host_path:type_name -> bass.HostPath + 26, // 12: bass.Value.thunk_path:type_name -> bass.ThunkPath + 28, // 13: bass.Value.logical_path:type_name -> bass.LogicalPath 2, // 14: bass.Value.thunk_addr:type_name -> bass.ThunkAddr - 4, // 15: bass.Thunk.image:type_name -> bass.ThunkImage - 8, // 16: bass.Thunk.cmd:type_name -> bass.ThunkCmd + 5, // 15: bass.Thunk.image:type_name -> bass.ThunkImage + 9, // 16: bass.Thunk.cmd:type_name -> bass.ThunkCmd 0, // 17: bass.Thunk.args:type_name -> bass.Value 0, // 18: bass.Thunk.stdin:type_name -> bass.Value - 14, // 19: bass.Thunk.env:type_name -> bass.Binding - 9, // 20: bass.Thunk.dir:type_name -> bass.ThunkDir - 11, // 21: bass.Thunk.mounts:type_name -> bass.ThunkMount - 14, // 22: bass.Thunk.labels:type_name -> bass.Binding + 15, // 19: bass.Thunk.env:type_name -> bass.Binding + 10, // 20: bass.Thunk.dir:type_name -> bass.ThunkDir + 12, // 21: bass.Thunk.mounts:type_name -> bass.ThunkMount + 15, // 22: bass.Thunk.labels:type_name -> bass.Binding 3, // 23: bass.Thunk.ports:type_name -> bass.ThunkPort - 1, // 24: bass.ThunkAddr.thunk:type_name -> bass.Thunk - 5, // 25: bass.ThunkImage.ref:type_name -> bass.ImageRef - 1, // 26: bass.ThunkImage.thunk:type_name -> bass.Thunk - 6, // 27: bass.ThunkImage.archive:type_name -> bass.ImageArchive - 25, // 28: bass.ImageRef.file:type_name -> bass.ThunkPath - 2, // 29: bass.ImageRef.addr:type_name -> bass.ThunkAddr - 7, // 30: bass.ImageRef.platform:type_name -> bass.Platform - 25, // 31: bass.ImageArchive.file:type_name -> bass.ThunkPath - 7, // 32: bass.ImageArchive.platform:type_name -> bass.Platform - 21, // 33: bass.ThunkCmd.command:type_name -> bass.CommandPath - 22, // 34: bass.ThunkCmd.file:type_name -> bass.FilePath - 25, // 35: bass.ThunkCmd.thunk:type_name -> bass.ThunkPath - 26, // 36: bass.ThunkCmd.host:type_name -> bass.HostPath - 27, // 37: bass.ThunkCmd.logical:type_name -> bass.LogicalPath - 19, // 38: bass.ThunkCmd.cache:type_name -> bass.CachePath - 23, // 39: bass.ThunkDir.local:type_name -> bass.DirPath - 25, // 40: bass.ThunkDir.thunk:type_name -> bass.ThunkPath - 26, // 41: bass.ThunkDir.host:type_name -> bass.HostPath - 25, // 42: bass.ThunkMountSource.thunk:type_name -> bass.ThunkPath - 26, // 43: bass.ThunkMountSource.host:type_name -> bass.HostPath - 27, // 44: bass.ThunkMountSource.logical:type_name -> bass.LogicalPath - 19, // 45: bass.ThunkMountSource.cache:type_name -> bass.CachePath - 20, // 46: bass.ThunkMountSource.secret:type_name -> bass.Secret - 10, // 47: bass.ThunkMount.source:type_name -> bass.ThunkMountSource - 24, // 48: bass.ThunkMount.target:type_name -> bass.FilesystemPath - 0, // 49: bass.Array.values:type_name -> bass.Value - 14, // 50: bass.Object.bindings:type_name -> bass.Binding - 0, // 51: bass.Binding.value:type_name -> bass.Value - 24, // 52: bass.CachePath.path:type_name -> bass.FilesystemPath - 22, // 53: bass.FilesystemPath.file:type_name -> bass.FilePath - 23, // 54: bass.FilesystemPath.dir:type_name -> bass.DirPath - 1, // 55: bass.ThunkPath.thunk:type_name -> bass.Thunk - 24, // 56: bass.ThunkPath.path:type_name -> bass.FilesystemPath - 24, // 57: bass.HostPath.path:type_name -> bass.FilesystemPath - 28, // 58: bass.LogicalPath.file:type_name -> bass.LogicalPath.File - 29, // 59: bass.LogicalPath.dir:type_name -> bass.LogicalPath.Dir - 27, // 60: bass.LogicalPath.Dir.entries:type_name -> bass.LogicalPath - 61, // [61:61] is the sub-list for method output_type - 61, // [61:61] is the sub-list for method input_type - 61, // [61:61] is the sub-list for extension type_name - 61, // [61:61] is the sub-list for extension extendee - 0, // [0:61] is the sub-list for field type_name + 4, // 24: bass.Thunk.tls:type_name -> bass.ThunkTLS + 1, // 25: bass.ThunkAddr.thunk:type_name -> bass.Thunk + 23, // 26: bass.ThunkTLS.cert:type_name -> bass.FilePath + 23, // 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 + 26, // 31: bass.ImageRef.file:type_name -> bass.ThunkPath + 2, // 32: bass.ImageRef.addr:type_name -> bass.ThunkAddr + 8, // 33: bass.ImageRef.platform:type_name -> bass.Platform + 26, // 34: bass.ImageArchive.file:type_name -> bass.ThunkPath + 8, // 35: bass.ImageArchive.platform:type_name -> bass.Platform + 22, // 36: bass.ThunkCmd.command:type_name -> bass.CommandPath + 23, // 37: bass.ThunkCmd.file:type_name -> bass.FilePath + 26, // 38: bass.ThunkCmd.thunk:type_name -> bass.ThunkPath + 27, // 39: bass.ThunkCmd.host:type_name -> bass.HostPath + 28, // 40: bass.ThunkCmd.logical:type_name -> bass.LogicalPath + 20, // 41: bass.ThunkCmd.cache:type_name -> bass.CachePath + 24, // 42: bass.ThunkDir.local:type_name -> bass.DirPath + 26, // 43: bass.ThunkDir.thunk:type_name -> bass.ThunkPath + 27, // 44: bass.ThunkDir.host:type_name -> bass.HostPath + 26, // 45: bass.ThunkMountSource.thunk:type_name -> bass.ThunkPath + 27, // 46: bass.ThunkMountSource.host:type_name -> bass.HostPath + 28, // 47: bass.ThunkMountSource.logical:type_name -> bass.LogicalPath + 20, // 48: bass.ThunkMountSource.cache:type_name -> bass.CachePath + 21, // 49: bass.ThunkMountSource.secret:type_name -> bass.Secret + 11, // 50: bass.ThunkMount.source:type_name -> bass.ThunkMountSource + 25, // 51: bass.ThunkMount.target:type_name -> bass.FilesystemPath + 0, // 52: bass.Array.values:type_name -> bass.Value + 15, // 53: bass.Object.bindings:type_name -> bass.Binding + 0, // 54: bass.Binding.value:type_name -> bass.Value + 25, // 55: bass.CachePath.path:type_name -> bass.FilesystemPath + 23, // 56: bass.FilesystemPath.file:type_name -> bass.FilePath + 24, // 57: bass.FilesystemPath.dir:type_name -> bass.DirPath + 1, // 58: bass.ThunkPath.thunk:type_name -> bass.Thunk + 25, // 59: bass.ThunkPath.path:type_name -> bass.FilesystemPath + 25, // 60: bass.HostPath.path:type_name -> bass.FilesystemPath + 29, // 61: bass.LogicalPath.file:type_name -> bass.LogicalPath.File + 30, // 62: bass.LogicalPath.dir:type_name -> bass.LogicalPath.Dir + 28, // 63: bass.LogicalPath.Dir.entries:type_name -> bass.LogicalPath + 64, // [64:64] is the sub-list for method output_type + 64, // [64:64] is the sub-list for method input_type + 64, // [64:64] is the sub-list for extension type_name + 64, // [64:64] is the sub-list for extension extendee + 0, // [0:64] is the sub-list for field type_name } func init() { file_bass_proto_init() } @@ -2603,7 +2678,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ThunkImage); i { + switch v := v.(*ThunkTLS); i { case 0: return &v.state case 1: @@ -2615,7 +2690,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ImageRef); i { + switch v := v.(*ThunkImage); i { case 0: return &v.state case 1: @@ -2627,7 +2702,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ImageArchive); i { + switch v := v.(*ImageRef); i { case 0: return &v.state case 1: @@ -2639,7 +2714,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Platform); i { + switch v := v.(*ImageArchive); i { case 0: return &v.state case 1: @@ -2651,7 +2726,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ThunkCmd); i { + switch v := v.(*Platform); i { case 0: return &v.state case 1: @@ -2663,7 +2738,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ThunkDir); i { + switch v := v.(*ThunkCmd); i { case 0: return &v.state case 1: @@ -2675,7 +2750,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ThunkMountSource); i { + switch v := v.(*ThunkDir); i { case 0: return &v.state case 1: @@ -2687,7 +2762,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ThunkMount); i { + switch v := v.(*ThunkMountSource); i { case 0: return &v.state case 1: @@ -2699,7 +2774,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Array); i { + switch v := v.(*ThunkMount); i { case 0: return &v.state case 1: @@ -2711,7 +2786,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Object); i { + switch v := v.(*Array); i { case 0: return &v.state case 1: @@ -2723,7 +2798,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Binding); i { + switch v := v.(*Object); i { case 0: return &v.state case 1: @@ -2735,7 +2810,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Null); i { + switch v := v.(*Binding); i { case 0: return &v.state case 1: @@ -2747,7 +2822,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Bool); i { + switch v := v.(*Null); i { case 0: return &v.state case 1: @@ -2759,7 +2834,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Int); i { + switch v := v.(*Bool); i { case 0: return &v.state case 1: @@ -2771,7 +2846,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*String); i { + switch v := v.(*Int); i { case 0: return &v.state case 1: @@ -2783,7 +2858,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CachePath); i { + switch v := v.(*String); i { case 0: return &v.state case 1: @@ -2795,7 +2870,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Secret); i { + switch v := v.(*CachePath); i { case 0: return &v.state case 1: @@ -2807,7 +2882,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CommandPath); i { + switch v := v.(*Secret); i { case 0: return &v.state case 1: @@ -2819,7 +2894,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FilePath); i { + switch v := v.(*CommandPath); i { case 0: return &v.state case 1: @@ -2831,7 +2906,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DirPath); i { + switch v := v.(*FilePath); i { case 0: return &v.state case 1: @@ -2843,7 +2918,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FilesystemPath); i { + switch v := v.(*DirPath); i { case 0: return &v.state case 1: @@ -2855,7 +2930,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ThunkPath); i { + switch v := v.(*FilesystemPath); i { case 0: return &v.state case 1: @@ -2867,7 +2942,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HostPath); i { + switch v := v.(*ThunkPath); i { case 0: return &v.state case 1: @@ -2879,7 +2954,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LogicalPath); i { + switch v := v.(*HostPath); i { case 0: return &v.state case 1: @@ -2891,7 +2966,7 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LogicalPath_File); i { + switch v := v.(*LogicalPath); i { case 0: return &v.state case 1: @@ -2903,6 +2978,18 @@ func file_bass_proto_init() { } } file_bass_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LogicalPath_File); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bass_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*LogicalPath_Dir); i { case 0: return &v.state @@ -2932,18 +3019,18 @@ func file_bass_proto_init() { (*Value_LogicalPath)(nil), (*Value_ThunkAddr)(nil), } - file_bass_proto_msgTypes[4].OneofWrappers = []interface{}{ + file_bass_proto_msgTypes[5].OneofWrappers = []interface{}{ (*ThunkImage_Ref)(nil), (*ThunkImage_Thunk)(nil), (*ThunkImage_Archive)(nil), } - file_bass_proto_msgTypes[5].OneofWrappers = []interface{}{ + file_bass_proto_msgTypes[6].OneofWrappers = []interface{}{ (*ImageRef_Repository)(nil), (*ImageRef_File)(nil), (*ImageRef_Addr)(nil), } - file_bass_proto_msgTypes[6].OneofWrappers = []interface{}{} - file_bass_proto_msgTypes[8].OneofWrappers = []interface{}{ + file_bass_proto_msgTypes[7].OneofWrappers = []interface{}{} + file_bass_proto_msgTypes[9].OneofWrappers = []interface{}{ (*ThunkCmd_Command)(nil), (*ThunkCmd_File)(nil), (*ThunkCmd_Thunk)(nil), @@ -2951,23 +3038,23 @@ func file_bass_proto_init() { (*ThunkCmd_Logical)(nil), (*ThunkCmd_Cache)(nil), } - file_bass_proto_msgTypes[9].OneofWrappers = []interface{}{ + file_bass_proto_msgTypes[10].OneofWrappers = []interface{}{ (*ThunkDir_Local)(nil), (*ThunkDir_Thunk)(nil), (*ThunkDir_Host)(nil), } - file_bass_proto_msgTypes[10].OneofWrappers = []interface{}{ + file_bass_proto_msgTypes[11].OneofWrappers = []interface{}{ (*ThunkMountSource_Thunk)(nil), (*ThunkMountSource_Host)(nil), (*ThunkMountSource_Logical)(nil), (*ThunkMountSource_Cache)(nil), (*ThunkMountSource_Secret)(nil), } - file_bass_proto_msgTypes[24].OneofWrappers = []interface{}{ + file_bass_proto_msgTypes[25].OneofWrappers = []interface{}{ (*FilesystemPath_File)(nil), (*FilesystemPath_Dir)(nil), } - file_bass_proto_msgTypes[27].OneofWrappers = []interface{}{ + file_bass_proto_msgTypes[28].OneofWrappers = []interface{}{ (*LogicalPath_File_)(nil), (*LogicalPath_Dir_)(nil), } @@ -2977,7 +3064,7 @@ func file_bass_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_bass_proto_rawDesc, NumEnums: 0, - NumMessages: 30, + NumMessages: 31, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/runtimes/buildkit.go b/pkg/runtimes/buildkit.go index d57f881a..a0096b34 100644 --- a/pkg/runtimes/buildkit.go +++ b/pkg/runtimes/buildkit.go @@ -17,6 +17,7 @@ import ( "github.com/adrg/xdg" "github.com/containerd/containerd/platforms" + dockerconfig "github.com/docker/cli/cli/config" "github.com/docker/distribution/reference" "github.com/hashicorp/go-multierror" "github.com/moby/buildkit/client" @@ -33,6 +34,7 @@ import ( ocispecs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/tonistiigi/units" "github.com/vito/bass/pkg/bass" + "github.com/vito/bass/pkg/basstls" "github.com/vito/bass/pkg/cli" "github.com/vito/bass/pkg/ioctx" "github.com/vito/bass/pkg/runtimes/util/buildkitd" @@ -40,7 +42,6 @@ import ( "github.com/vito/progrock" "github.com/vito/progrock/graph" "go.uber.org/zap" - "golang.org/x/sync/errgroup" _ "embed" ) @@ -48,8 +49,10 @@ import ( const buildkitProduct = "bass" type BuildkitConfig struct { + Debug bool `json:"debug,omitempty"` Addr string `json:"addr,omitempty"` DisableCache bool `json:"disable_cache,omitempty"` + CertsDir string `json:"certs_dir,omitempty"` } var _ bass.Runtime = &Buildkit{} @@ -64,6 +67,7 @@ const workDir = "/bass/work" const ioDir = "/bass/io" const inputFile = "/bass/io/in" const outputFile = "/bass/io/out" +const caFile = "/bass/ca.crt" const digestBucket = "_digests" const configBucket = "_configs" @@ -100,6 +104,15 @@ func NewBuildkit(ctx context.Context, _ bass.RuntimePool, cfg *bass.Scope) (bass } } + if config.CertsDir == "" { + config.CertsDir = basstls.DefaultDir + } + + err := basstls.Init(config.CertsDir) + if err != nil { + return nil, fmt.Errorf("init tls depot: %w", err) + } + client, err := dialBuildkit(ctx, config.Addr) if err != nil { return nil, fmt.Errorf("dial buildkit: %w", err) @@ -126,7 +139,7 @@ func NewBuildkit(ctx context.Context, _ bass.RuntimePool, cfg *bass.Scope) (bass Client: client, Platform: platform, - authp: authprovider.NewDockerAuthProvider(os.Stderr), + authp: authprovider.NewDockerAuthProvider(dockerconfig.LoadDefaultConfigFile(os.Stderr)), }, nil } @@ -230,12 +243,16 @@ func (runtime *Buildkit) Start(ctx context.Context, thunk bass.Thunk) (StartResu host := thunk.Name() - health := runtime.newHealth(ctx, host, thunk.Ports) - - health.Start() + health := runtime.newHealth(host, thunk.Ports) runs := bass.RunsFromContext(ctx) + checked := make(chan error, 1) + runs.Go(stop, func() error { + checked <- health.Check(ctx) + return nil + }) + exited := make(chan error, 1) runs.Go(stop, func() error { exited <- runtime.build( @@ -247,26 +264,33 @@ func (runtime *Buildkit) Start(ctx context.Context, thunk bass.Thunk) (StartResu nil, // exports llb.IgnoreCache, // never cache services ) - return nil // disregard err; services don't have to exit cleanly + + return nil }) - result := StartResult{ - Ports: PortInfos{}, - } + select { + case <-checked: + result := StartResult{ + Ports: PortInfos{}, + } - for _, port := range thunk.Ports { - result.Ports[port.Name] = bass.Bindings{ - "host": bass.String(host), - "port": bass.Int(port.Port), - }.Scope() - } + for _, port := range thunk.Ports { + result.Ports[port.Name] = bass.Bindings{ + "host": bass.String(host), + "port": bass.Int(port.Port), + }.Scope() + } - err := health.Wait() - if err != nil { - return StartResult{}, err - } + return result, nil + case err := <-exited: + stop() // interrupt healthcheck + + if err != nil { + return StartResult{}, err + } - return result, nil + return StartResult{}, fmt.Errorf("service exited before healthcheck") + } } func (runtime *Buildkit) Read(ctx context.Context, w io.Writer, thunk bass.Thunk) error { @@ -494,38 +518,27 @@ func result(ctx context.Context, gw gwclient.Client, st marshalable) (*gwclient. type portHealthChecker struct { runtime *Buildkit - eg *errgroup.Group - ctx context.Context host string ports []bass.ThunkPort } -func (runtime *Buildkit) newHealth(ctx context.Context, host string, ports []bass.ThunkPort) *portHealthChecker { - eg, ctx := errgroup.WithContext(ctx) +func (runtime *Buildkit) newHealth(host string, ports []bass.ThunkPort) *portHealthChecker { return &portHealthChecker{ runtime: runtime, - eg: eg, - ctx: ctx, host: host, ports: ports, } } -func (d *portHealthChecker) Start() { - d.eg.Go(func() error { - _, err := d.runtime.Client.Build(d.ctx, kitdclient.SolveOpt{ - Session: []session.Attachable{ - d.runtime.authp, - }, - }, buildkitProduct, d.doBuild, nil) - return err - }) -} - -func (d *portHealthChecker) Wait() error { - return d.eg.Wait() +func (d *portHealthChecker) Check(ctx context.Context) error { + _, err := d.runtime.Client.Build(ctx, kitdclient.SolveOpt{ + Session: []session.Attachable{ + d.runtime.authp, + }, + }, buildkitProduct, d.doBuild, nil) + return err } func (d *portHealthChecker) doBuild(ctx context.Context, gw gwclient.Client) (*gwclient.Result, error) { @@ -565,7 +578,7 @@ func (d *portHealthChecker) doBuild(ctx context.Context, gw gwclient.Client) (*g defer container.Release(ctx) - args := []string{shimExePath, "check", d.host + ".dns.bass"} + args := []string{shimExePath, "check", d.host} for _, port := range d.ports { args = append(args, fmt.Sprintf("%s:%d", port.Name, port.Port)) } @@ -630,6 +643,11 @@ func (b *builder) llb(ctx context.Context, thunk bass.Thunk, extraOpts ...llb.Ru return llb.ExecState{}, "", false, err } + rootCA, err := os.ReadFile(basstls.CACert(b.runtime.Config.CertsDir)) + if err != nil { + return llb.ExecState{}, "", false, err + } + runOpt := []llb.RunOption{ llb.WithCustomName(thunk.Cmdline()), // NB: this is load-bearing; it's what busts the cache with different labels @@ -641,10 +659,54 @@ func (b *builder) llb(ctx context.Context, thunk bass.Thunk, extraOpts ...llb.Ru llb.WithCustomName("[hide] mount command json"), )), llb.AddMount(shimExePath, shimExe, llb.SourcePath("run")), + llb.AddMount(caFile, llb.Scratch().File( + llb.Mkfile("ca.crt", 0600, rootCA), + llb.WithCustomName("[hide] mount bass ca"), + ), llb.SourcePath("ca.crt")), llb.With(llb.Dir(workDir)), llb.Args([]string{shimExePath, "run", inputFile}), } + if thunk.TLS != nil { + crt, key, err := basstls.Generate(b.runtime.Config.CertsDir, id) + if err != nil { + return llb.ExecState{}, "", false, fmt.Errorf("tls: generate: %w", err) + } + + crtContent, err := crt.Export() + if err != nil { + return llb.ExecState{}, "", false, fmt.Errorf("export crt: %w", err) + } + + keyContent, err := key.ExportPrivate() + if err != nil { + return llb.ExecState{}, "", false, fmt.Errorf("export key: %w", err) + } + + runOpt = append(runOpt, + llb.AddMount( + thunk.TLS.Cert.FromSlash(), + llb.Scratch().File( + llb.Mkfile(thunk.TLS.Cert.Name(), 0600, crtContent), + llb.WithCustomName("[hide] mount thunk tls cert"), + ), + llb.SourcePath(thunk.TLS.Cert.Name()), + ), + llb.AddMount( + thunk.TLS.Key.FromSlash(), + llb.Scratch().File( + llb.Mkfile(thunk.TLS.Key.Name(), 0600, keyContent), + llb.WithCustomName("[hide] mount thunk tls key"), + ), + llb.SourcePath(thunk.TLS.Key.Name()), + ), + ) + } + + if b.runtime.Config.Debug { + runOpt = append(runOpt, llb.AddEnv("_BASS_DEBUG", "1")) + } + if thunk.Insecure { needsInsecure = true diff --git a/pkg/runtimes/buildkit_test.go b/pkg/runtimes/buildkit_test.go index 8954bf48..fd47c4b4 100644 --- a/pkg/runtimes/buildkit_test.go +++ b/pkg/runtimes/buildkit_test.go @@ -2,6 +2,7 @@ package runtimes_test import ( "context" + "os" "testing" _ "github.com/moby/buildkit/client" @@ -20,11 +21,18 @@ func TestBuildkitRuntime(t *testing.T) { ctx := context.Background() + is.NoErr(os.Chmod("./testdata/tls/bass.crt", 0400)) + is.NoErr(os.Chmod("./testdata/tls/bass.key", 0400)) + pool, err := runtimes.NewPool(ctx, &bass.Config{ Runtimes: []bass.RuntimeConfig{ { Platform: bass.LinuxPlatform, Runtime: runtimes.BuildkitName, + Config: bass.Bindings{ + "debug": bass.Bool(true), + "certs_dir": bass.String("./testdata/tls/"), + }.Scope(), }, }, }) diff --git a/pkg/runtimes/command_test.go b/pkg/runtimes/command_test.go index 7759b25e..ca817827 100644 --- a/pkg/runtimes/command_test.go +++ b/pkg/runtimes/command_test.go @@ -41,6 +41,14 @@ var svcThunk = bass.Thunk{ Name: "http", Port: 80, }, + { + Name: "https", + Port: 443, + }, + }, + TLS: &bass.ThunkTLS{ + Cert: bass.FilePath{Path: "cert"}, + Key: bass.FilePath{Path: "key"}, }, } diff --git a/pkg/runtimes/shim/check.go b/pkg/runtimes/shim/check.go new file mode 100644 index 00000000..1a52e29f --- /dev/null +++ b/pkg/runtimes/shim/check.go @@ -0,0 +1,79 @@ +package main + +import ( + "fmt" + "net" + "strings" + "time" + + "github.com/cenkalti/backoff/v4" + "go.uber.org/zap" +) + +func check(args []string) error { + logger := StdLogger(logLevel) + + if len(args) == 0 { + return fmt.Errorf("usage: check name:port...") + } + + host, ports := args[0], args[1:] + + for _, nameAndPort := range ports { + name, port, ok := strings.Cut(nameAndPort, ":") + if !ok { + return fmt.Errorf("port must be in form name:number: %s", nameAndPort) + } + + logger := logger.With(zap.String("name", name), zap.String("port", port)) + + logger.Debug("polling for port") + + pollAddr := net.JoinHostPort(host, port) + + reached, err := pollForPort(logger, pollAddr) + if err != nil { + return fmt.Errorf("poll %s: %w", name, err) + } + + logger.Info("port is up", zap.String("reached", reached)) + } + + return nil +} + +func pollForPort(logger *zap.Logger, addr string) (string, error) { + retry := backoff.NewExponentialBackOff() + retry.InitialInterval = 100 * time.Millisecond + + dialer := net.Dialer{ + Timeout: time.Second, + } + + var reached string + err := backoff.Retry(func() error { + conn, err := dialer.Dial("tcp", addr) + if err != nil { + logger.Debug("failed to dial", zap.Duration("elapsed", retry.GetElapsedTime()), zap.Error(err)) + return err + } + + host, _, err := net.SplitHostPort(conn.RemoteAddr().String()) + if err != nil { + // don't know how this would happen but it's likely not recoverable + logger.Error("malformed host:port", zap.Error(err)) + return backoff.Permanent(err) + } + + reached = host + + _ = conn.Close() + + return nil + }, retry) + if err != nil { + return "", err + } + + return reached, nil +} diff --git a/pkg/runtimes/shim/get_config.go b/pkg/runtimes/shim/get_config.go new file mode 100644 index 00000000..43cc3a44 --- /dev/null +++ b/pkg/runtimes/shim/get_config.go @@ -0,0 +1,91 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + + ispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/opencontainers/umoci/oci/casext" +) + +func getConfig(args []string) error { + ctx := context.Background() + + if len(args) != 3 { + return fmt.Errorf("usage: get-config image.tar tag dest/") + } + + archiveSrc := args[0] + fromName := args[1] + configDst := args[2] + + layout, err := openTar(archiveSrc) + if err != nil { + return fmt.Errorf("create layout: %w", err) + } + + defer layout.Close() + + ext := casext.NewEngine(layout) + + mspec, err := loadManifest(ctx, ext, fromName) + if err != nil { + return err + } + + config, err := ext.FromDescriptor(ctx, mspec.Config) + if err != nil { + return fmt.Errorf("load config: %w", err) + } + + if config.Descriptor.MediaType != ispec.MediaTypeImageConfig { + return fmt.Errorf("bad config media type: %s", config.Descriptor.MediaType) + } + + ispec := config.Data.(ispec.Image) + + configPath := filepath.Join(configDst, "config.json") + + configFile, err := os.Create(configPath) + if err != nil { + return fmt.Errorf("create config.json: %w", err) + } + + defer configFile.Close() + + err = json.NewEncoder(configFile).Encode(ispec.Config) + if err != nil { + return fmt.Errorf("encode image config: %w", err) + } + + return nil +} + +func loadManifest(ctx context.Context, ext casext.Engine, name string) (ispec.Manifest, error) { + descPaths, err := ext.ResolveReference(context.Background(), name) + if err != nil { + return ispec.Manifest{}, fmt.Errorf("resolve ref: %w", err) + } + + if len(descPaths) == 0 { + return ispec.Manifest{}, fmt.Errorf("tag not found: %s", name) + } + + if len(descPaths) != 1 { + return ispec.Manifest{}, fmt.Errorf("ambiguous tag?: %s (%d paths returned)", name, len(descPaths)) + } + + manifest, err := ext.FromDescriptor(ctx, descPaths[0].Descriptor()) + if err != nil { + return ispec.Manifest{}, fmt.Errorf("load manifest: %w", err) + } + + if manifest.Descriptor.MediaType != ispec.MediaTypeImageManifest { + return ispec.Manifest{}, fmt.Errorf("bad manifest media type: %s", manifest.Descriptor.MediaType) + } + + return manifest.Data.(ispec.Manifest), nil +} diff --git a/pkg/runtimes/shim/log.go b/pkg/runtimes/shim/log.go new file mode 100644 index 00000000..f3cf33b2 --- /dev/null +++ b/pkg/runtimes/shim/log.go @@ -0,0 +1,52 @@ +package main + +import ( + "io" + "net" + "time" + + "github.com/mattn/go-colorable" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +// yoinked from pkg/bass/log.go, avoiding too many dependencies +func LoggerTo(w io.Writer, level zapcore.LevelEnabler) *zap.Logger { + zapcfg := zap.NewDevelopmentEncoderConfig() + zapcfg.EncodeLevel = zapcore.LowercaseColorLevelEncoder + zapcfg.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { + enc.AppendString(t.Format("15:04:05.000")) + } + + return zap.New(zapcore.NewCore( + zapcore.NewConsoleEncoder(zapcfg), + zapcore.AddSync(w), + level, + )) +} + +func StdLogger(level zapcore.LevelEnabler) *zap.Logger { + return LoggerTo(colorable.NewColorableStderr(), level) +} + +func logIPs(logger *zap.Logger) { + ifaces, err := net.Interfaces() + if err != nil { + logger.Error("failed to get interfaces", zap.Error(err)) + return + } + + for _, i := range ifaces { + logger = logger.With(zap.String("iface", i.Name)) + + addrs, err := i.Addrs() + if err != nil { + logger.Error("failed to get addrs", zap.Error(err)) + continue + } + + for _, addr := range addrs { + logger.Debug("addr", zap.String("addr", addr.String())) + } + } +} diff --git a/pkg/runtimes/shim/main.go b/pkg/runtimes/shim/main.go index c2fb43c6..8dee16b3 100644 --- a/pkg/runtimes/shim/main.go +++ b/pkg/runtimes/shim/main.go @@ -1,63 +1,25 @@ package main import ( - "archive/tar" - "bytes" - "context" - "encoding/json" - "errors" "fmt" - "io" - "io/fs" - "net" "os" - "os/exec" - "os/signal" - "path" - "path/filepath" - "runtime" "sort" "strings" - "syscall" - "time" - "github.com/cenkalti/backoff/v4" - "github.com/containerd/containerd/sys/reaper" - "github.com/mattn/go-colorable" - "github.com/moby/sys/mountinfo" - "github.com/opencontainers/go-digest" - ispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/opencontainers/umoci/oci/cas" - "github.com/opencontainers/umoci/oci/casext" - "github.com/opencontainers/umoci/oci/layer" - "go.uber.org/zap" "go.uber.org/zap/zapcore" - "golang.org/x/sys/unix" ) -// NB: change this to Debug if you're troubleshooting the shim -const LogLevel = zapcore.ErrorLevel - -type Command struct { - Args []string `json:"args"` - Stdin []byte `json:"stdin"` - Env []string `json:"env"` - Dir *string `json:"dir"` -} - -var stdoutPath string -var pingAddr string +var debug bool +var logLevel = zapcore.ErrorLevel func init() { - stdoutPath = os.Getenv("_BASS_OUTPUT") - os.Unsetenv("_BASS_OUTPUT") - - pingAddr = os.Getenv("_BASS_PING") - os.Unsetenv("_BASS_PING") + if os.Getenv("_BASS_DEBUG") != "" { + debug = true + logLevel = zapcore.DebugLevel + os.Unsetenv("_BASS_DEBUG") + } } -const cidr = "10.0.0.0/8" - var cmds = map[string]func([]string) error{ "run": run, "unpack": unpack, @@ -100,535 +62,3 @@ func main() { os.Exit(1) } } - -func run(args []string) error { - runtime.GOMAXPROCS(1) - - if len(args) != 1 { - return fmt.Errorf("usage: run ") - } - - err := reap() - if err != nil { - return fmt.Errorf("reap: %w", err) - } - - cmdPath := args[0] - - if pingAddr != "" { - err := ping(pingAddr) - if err != nil { - return err - } - } - - cmdPayload, err := os.ReadFile(cmdPath) - if err != nil { - return fmt.Errorf("read cmd: %w", err) - } - - var cmd Command - err = json.Unmarshal(cmdPayload, &cmd) - if err != nil { - return fmt.Errorf("unmarshal cmd: %w", err) - } - - err = os.Remove(cmdPath) - if err != nil { - return fmt.Errorf("burn after reading: %w", err) - } - - var stdout io.Writer = os.Stdout - if stdoutPath != "" { - response, err := os.Create(stdoutPath) - if err != nil { - return fmt.Errorf("create output error: %w", err) - } - - defer response.Close() - - stdout = response - } - - for _, e := range cmd.Env { - segs := strings.SplitN(e, "=", 2) - if len(segs) != 2 { - return fmt.Errorf("malformed env: %s", e) - } - - os.Setenv(segs[0], segs[1]) - } - - bin := cmd.Args[0] - argv := cmd.Args[1:] - execCmd := exec.Command(bin, argv...) - if cmd.Dir != nil { - execCmd.Dir = *cmd.Dir - } - execCmd.Stdin = bytes.NewBuffer(cmd.Stdin) - execCmd.Stdout = stdout - execCmd.Stderr = os.Stderr - - ch, err := reaper.Default.Start(execCmd) - if err != nil { - return fmt.Errorf("start: %w", err) - } - - status, err := reaper.Default.Wait(execCmd, ch) - if err != nil { - return fmt.Errorf("wait: %w", err) - } - - if status != 0 { - // propagate exit status - os.Exit(status) - return nil - } - - err = normalizeTimes(".") - if err != nil { - return fmt.Errorf("failed to normalize timestamps: %w", err) - } - - return nil -} - -func reap() error { - logger := StdLogger(LogLevel) - - reaper.SetSubreaper(1) - - children := make(chan os.Signal) - signal.Notify(children, syscall.SIGCHLD) - - go func() { - for range children { - err := reaper.Reap() - if err != nil { - logger.Warn("failed to reap", zap.Error(err)) - } - } - }() - - return nil -} - -func getConfig(args []string) error { - ctx := context.Background() - - if len(args) != 3 { - return fmt.Errorf("usage: get-config image.tar tag dest/") - } - - archiveSrc := args[0] - fromName := args[1] - configDst := args[2] - - layout, err := openTar(archiveSrc) - if err != nil { - return fmt.Errorf("create layout: %w", err) - } - - defer layout.Close() - - ext := casext.NewEngine(layout) - - mspec, err := loadManifest(ctx, ext, fromName) - if err != nil { - return err - } - - config, err := ext.FromDescriptor(ctx, mspec.Config) - if err != nil { - return fmt.Errorf("load config: %w", err) - } - - if config.Descriptor.MediaType != ispec.MediaTypeImageConfig { - return fmt.Errorf("bad config media type: %s", config.Descriptor.MediaType) - } - - ispec := config.Data.(ispec.Image) - - configPath := filepath.Join(configDst, "config.json") - - configFile, err := os.Create(configPath) - if err != nil { - return fmt.Errorf("create config.json: %w", err) - } - - defer configFile.Close() - - err = json.NewEncoder(configFile).Encode(ispec.Config) - if err != nil { - return fmt.Errorf("encode image config: %w", err) - } - - return nil -} - -func unpack(args []string) error { - ctx := context.Background() - - if len(args) != 3 { - return fmt.Errorf("usage: unpack ") - } - - archiveSrc := args[0] - fromName := args[1] - rootfsPath := args[2] - - layout, err := openTar(archiveSrc) - if err != nil { - return fmt.Errorf("create layout: %w", err) - } - - defer layout.Close() - - ext := casext.NewEngine(layout) - - mspec, err := loadManifest(ctx, ext, fromName) - if err != nil { - return err - } - - err = layer.UnpackRootfs(context.Background(), ext, rootfsPath, mspec, &layer.UnpackOptions{}) - if err != nil { - return fmt.Errorf("unpack rootfs: %w", err) - } - - return nil -} - -func loadManifest(ctx context.Context, ext casext.Engine, name string) (ispec.Manifest, error) { - descPaths, err := ext.ResolveReference(context.Background(), name) - if err != nil { - return ispec.Manifest{}, fmt.Errorf("resolve ref: %w", err) - } - - if len(descPaths) == 0 { - return ispec.Manifest{}, fmt.Errorf("tag not found: %s", name) - } - - if len(descPaths) != 1 { - return ispec.Manifest{}, fmt.Errorf("ambiguous tag?: %s (%d paths returned)", name, len(descPaths)) - } - - manifest, err := ext.FromDescriptor(ctx, descPaths[0].Descriptor()) - if err != nil { - return ispec.Manifest{}, fmt.Errorf("load manifest: %w", err) - } - - if manifest.Descriptor.MediaType != ispec.MediaTypeImageManifest { - return ispec.Manifest{}, fmt.Errorf("bad manifest media type: %s", manifest.Descriptor.MediaType) - } - - return manifest.Data.(ispec.Manifest), nil -} - -func openTar(tarPath string) (cas.Engine, error) { - archive, err := os.Open(tarPath) - if err != nil { - return nil, err - } - - return &tarEngine{archive}, nil -} - -// tarEngine implements a read-only cas.Engine backed by a .tar archive. -type tarEngine struct { - archive *os.File -} - -func (engine *tarEngine) PutBlob(ctx context.Context, reader io.Reader) (digest.Digest, int64, error) { - return "", 0, fmt.Errorf("PutBlob: %w", cas.ErrNotImplemented) -} - -func (engine *tarEngine) GetBlob(ctx context.Context, dig digest.Digest) (io.ReadCloser, error) { - r, err := engine.open(path.Join("blobs", dig.Algorithm().String(), dig.Encoded())) - if err != nil { - return nil, err - } - - return io.NopCloser(r), nil -} - -func (engine *tarEngine) StatBlob(ctx context.Context, dig digest.Digest) (bool, error) { - _, err := engine.open(path.Join("blobs", dig.Algorithm().String(), dig.Encoded())) - if err != nil { - if errors.Is(err, cas.ErrNotExist) { - return false, nil - } - - return false, err - } - - return true, nil -} - -func (engine *tarEngine) PutIndex(ctx context.Context, index ispec.Index) error { - return fmt.Errorf("PutIndex: %w", cas.ErrNotImplemented) -} - -func (engine *tarEngine) GetIndex(ctx context.Context) (ispec.Index, error) { - var idx ispec.Index - r, err := engine.open("index.json") - if err != nil { - return ispec.Index{}, err - } - - err = json.NewDecoder(r).Decode(&idx) - if err != nil { - return ispec.Index{}, err - } - - return idx, nil -} - -func (engine *tarEngine) open(p string) (io.Reader, error) { - _, err := engine.archive.Seek(0, 0) - if err != nil { - return nil, fmt.Errorf("seek: %w", err) - } - - tr := tar.NewReader(engine.archive) - - for { - hdr, err := tr.Next() - if err != nil { - if err == io.EOF { - return nil, fmt.Errorf("open %s: %w", p, cas.ErrNotExist) - } - - return nil, err - } - - if path.Clean(hdr.Name) == p { - return tr, nil - } - } -} - -func (engine *tarEngine) DeleteBlob(ctx context.Context, digest digest.Digest) (err error) { - return fmt.Errorf("DeleteBlob: %w", cas.ErrNotImplemented) -} - -func (engine *tarEngine) ListBlobs(ctx context.Context) ([]digest.Digest, error) { - _, err := engine.archive.Seek(0, 0) - if err != nil { - return nil, fmt.Errorf("seek: %w", err) - } - - tr := tar.NewReader(engine.archive) - - var digs []digest.Digest - for { - hdr, err := tr.Next() - if err != nil { - if err == io.EOF { - break - } - - return nil, fmt.Errorf("next: %w", err) - } - - if strings.HasPrefix(path.Clean(hdr.Name), "blobs/") { - dir, encoded := path.Split(hdr.Name) - _, alg := path.Split(dir) - digs = append(digs, digest.NewDigestFromEncoded(digest.Algorithm(alg), encoded)) - } - } - - return digs, nil -} - -func (engine *tarEngine) Clean(ctx context.Context) error { return nil } - -func (engine *tarEngine) Close() error { - return engine.archive.Close() -} - -var epoch = time.Date(1985, 10, 26, 8, 15, 0, 0, time.UTC) - -func normalizeTimes(root string) error { - logger := StdLogger(LogLevel) - - skipped := 0 - unchanged := 0 - changed := 0 - start := time.Now() - tspec := unix.NsecToTimespec(epoch.UnixNano()) - targetTime := []unix.Timespec{tspec, tspec} - err := filepath.Walk(root, func(path string, info fs.FileInfo, err error) error { - if path != root && info.IsDir() { - mp, err := mountinfo.Mounted(path) - if err != nil { - return fmt.Errorf("check mounted: %w", err) - } - - if mp { - logger.Debug("skipping mountpoint", zap.String("path", path)) - skipped++ - return fs.SkipDir - } - } - - if info.ModTime().Equal(epoch) { - unchanged++ - return nil - } - - changed++ - - logger.Debug("chtimes", - zap.String("path", path), - zap.Time("from", info.ModTime()), - zap.Time("to", epoch)) - - err = unix.UtimesNanoAt(unix.AT_FDCWD, path, targetTime, unix.AT_SYMLINK_NOFOLLOW) - if err != nil { - return fmt.Errorf("chtimes: %w", err) - } - - return nil - }) - if err != nil { - return err - } - - logger.Info("times normalized", - zap.Duration("took", time.Since(start)), - zap.Int("changed", changed), - zap.Int("unchanged", unchanged), - zap.Int("skipped", skipped), - ) - - return nil -} - -func check(args []string) error { - logger := StdLogger(LogLevel) - - if len(args) == 0 { - return fmt.Errorf("usage: check name:port...") - } - - host, ports := args[0], args[1:] - - for _, nameAndPort := range ports { - name, port, ok := strings.Cut(nameAndPort, ":") - if !ok { - return fmt.Errorf("port must be in form name:number: %s", nameAndPort) - } - - logger := logger.With(zap.String("name", name), zap.String("port", port)) - - logger.Debug("polling for port") - - pollAddr := net.JoinHostPort(host, port) - - err := pollForPort(logger, pollAddr) - if err != nil { - return fmt.Errorf("poll %s: %w", name, err) - } - - logger.Info("port is up") - } - - return nil -} - -func containerIP() (net.IP, error) { - ifaces, err := net.Interfaces() - if err != nil { - return nil, err - } - - _, blk, err := net.ParseCIDR(cidr) - if err != nil { - return nil, err - } - - for _, i := range ifaces { - addrs, err := i.Addrs() - if err != nil { - return nil, err - } - - for _, addr := range addrs { - var ip net.IP - switch v := addr.(type) { - case *net.IPNet: - ip = v.IP - case *net.IPAddr: - ip = v.IP - } - - if blk.Contains(ip) { - return ip, nil - } - } - } - - return nil, fmt.Errorf("could not determine container IP (must be in %s)", cidr) -} - -func ping(addr string) error { - ip, err := containerIP() - if err != nil { - return err - } - - conn, err := net.Dial("tcp", pingAddr) - if err != nil { - return fmt.Errorf("ping: %w", err) - } - - defer conn.Close() - - _, err = io.WriteString(conn, ip.String()) - if err != nil { - return fmt.Errorf("write host: %w", err) - } - - return nil -} - -func pollForPort(logger *zap.Logger, addr string) error { - retry := backoff.NewExponentialBackOff() - retry.InitialInterval = 100 * time.Millisecond - - dialer := net.Dialer{ - Timeout: time.Second, - } - - return backoff.Retry(func() error { - conn, err := dialer.Dial("tcp", addr) - if err != nil { - logger.Debug("failed to dial", zap.Duration("elapsed", retry.GetElapsedTime()), zap.Error(err)) - return err - } - - _ = conn.Close() - - return nil - }, retry) -} - -// yoinked from pkg/bass/log.go, avoiding too many dependencies -func LoggerTo(w io.Writer, level zapcore.LevelEnabler) *zap.Logger { - zapcfg := zap.NewDevelopmentEncoderConfig() - zapcfg.EncodeLevel = zapcore.LowercaseColorLevelEncoder - zapcfg.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { - enc.AppendString(t.Format("15:04:05.000")) - } - - return zap.New(zapcore.NewCore( - zapcore.NewConsoleEncoder(zapcfg), - zapcore.AddSync(w), - level, - )) -} - -func StdLogger(level zapcore.LevelEnabler) *zap.Logger { - return LoggerTo(colorable.NewColorableStderr(), level) -} diff --git a/pkg/runtimes/shim/run.go b/pkg/runtimes/shim/run.go new file mode 100644 index 00000000..c653df64 --- /dev/null +++ b/pkg/runtimes/shim/run.go @@ -0,0 +1,208 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "io/fs" + "os" + "os/exec" + "os/signal" + "path/filepath" + "strings" + "syscall" + "time" + + "github.com/containerd/containerd/sys/reaper" + "github.com/moby/sys/mountinfo" + "go.uber.org/zap" + "golang.org/x/sys/unix" +) + +type Command struct { + Args []string `json:"args"` + Stdin []byte `json:"stdin"` + Env []string `json:"env"` + Dir *string `json:"dir"` +} + +func run(args []string) error { + if len(args) != 1 { + return fmt.Errorf("usage: run ") + } + + logger := StdLogger(logLevel) + + if debug { + hn, err := os.Hostname() + if err != nil { + return fmt.Errorf("get hostname: %w", err) + } + + logger.Debug("starting", zap.String("hostname", hn)) + + logIPs(logger) + } + + if err := installCert(); err != nil { + return fmt.Errorf("install bass CA: %w", err) + } + + if err := spawnReaper(); err != nil { + return fmt.Errorf("reap: %w", err) + } + + cmdPath := args[0] + + cmdPayload, err := os.ReadFile(cmdPath) + if err != nil { + return fmt.Errorf("read cmd: %w", err) + } + + var cmd Command + err = json.Unmarshal(cmdPayload, &cmd) + if err != nil { + return fmt.Errorf("unmarshal cmd: %w", err) + } + + err = os.Remove(cmdPath) + if err != nil { + return fmt.Errorf("burn after reading: %w", err) + } + + stdoutPath := os.Getenv("_BASS_OUTPUT") + os.Unsetenv("_BASS_OUTPUT") + + var stdout io.Writer = os.Stdout + if stdoutPath != "" { + response, err := os.Create(stdoutPath) + if err != nil { + return fmt.Errorf("create output error: %w", err) + } + + defer response.Close() + + stdout = response + } + + for _, e := range cmd.Env { + segs := strings.SplitN(e, "=", 2) + if len(segs) != 2 { + return fmt.Errorf("malformed env: %s", e) + } + + os.Setenv(segs[0], segs[1]) + } + + bin := cmd.Args[0] + argv := cmd.Args[1:] + execCmd := exec.Command(bin, argv...) + if cmd.Dir != nil { + execCmd.Dir = *cmd.Dir + } + execCmd.Stdin = bytes.NewBuffer(cmd.Stdin) + execCmd.Stdout = stdout + execCmd.Stderr = os.Stderr + + ch, err := reaper.Default.Start(execCmd) + if err != nil { + return fmt.Errorf("start: %w", err) + } + + status, err := reaper.Default.Wait(execCmd, ch) + if err != nil { + return fmt.Errorf("wait: %w", err) + } + + if status != 0 { + // propagate exit status + os.Exit(status) + return nil + } + + err = normalizeTimes(".") + if err != nil { + return fmt.Errorf("failed to normalize timestamps: %w", err) + } + + return nil +} + +func spawnReaper() error { + logger := StdLogger(logLevel) + + reaper.SetSubreaper(1) + + children := make(chan os.Signal, 32) + signal.Notify(children, syscall.SIGCHLD) + + go func() { + for range children { + err := reaper.Reap() + if err != nil { + logger.Warn("failed to reap", zap.Error(err)) + } + } + }() + + return nil +} + +var epoch = time.Date(1985, 10, 26, 8, 15, 0, 0, time.UTC) + +func normalizeTimes(root string) error { + logger := StdLogger(logLevel) + + skipped := 0 + unchanged := 0 + changed := 0 + start := time.Now() + tspec := unix.NsecToTimespec(epoch.UnixNano()) + targetTime := []unix.Timespec{tspec, tspec} + err := filepath.Walk(root, func(path string, info fs.FileInfo, err error) error { + if path != root && info.IsDir() { + mp, err := mountinfo.Mounted(path) + if err != nil { + return fmt.Errorf("check mounted: %w", err) + } + + if mp { + logger.Debug("skipping mountpoint", zap.String("path", path)) + skipped++ + return fs.SkipDir + } + } + + if info.ModTime().Equal(epoch) { + unchanged++ + return nil + } + + changed++ + + logger.Debug("chtimes", + zap.String("path", path), + zap.Time("from", info.ModTime()), + zap.Time("to", epoch)) + + err = unix.UtimesNanoAt(unix.AT_FDCWD, path, targetTime, unix.AT_SYMLINK_NOFOLLOW) + if err != nil { + return fmt.Errorf("chtimes: %w", err) + } + + return nil + }) + if err != nil { + return err + } + + logger.Info("times normalized", + zap.Duration("took", time.Since(start)), + zap.Int("changed", changed), + zap.Int("unchanged", unchanged), + zap.Int("skipped", skipped), + ) + + return nil +} diff --git a/pkg/runtimes/shim/tls.go b/pkg/runtimes/shim/tls.go new file mode 100644 index 00000000..b81bdc85 --- /dev/null +++ b/pkg/runtimes/shim/tls.go @@ -0,0 +1,115 @@ +package main + +import ( + "fmt" + "io" + "os" + "os/exec" + "path/filepath" +) + +var ( + BassCAFile = "/bass/ca.crt" +) + +var trusts = map[string][]string{ + "/usr/local/share/ca-certificates/%s.crt": { + "update-ca-certificates", + }, + "/usr/share/pki/trust/anchors/%s.pem": { + "update-ca-certificates", + }, + "/etc/pki/ca-trust/source/anchors/%s.pem": { + "update-ca-trust", "extract", + }, + "/etc/ca-certificates/trust-source/anchors/%s.crt": { + "trust", "extract-compat", + }, +} + +var bundles = []string{ + // alpine, ubuntu + "/etc/ssl/certs/ca-certificates.crt", + // nixery + "/etc/ssl/certs/ca-bundle.crt", +} + +func pathExists(path string) bool { + _, err := os.Stat(path) + return err == nil +} + +func binaryExists(name string) bool { + _, err := exec.LookPath(name) + return err == nil +} + +func installCert() error { + // first try to install gracefully to the system trust + for pathTemplate, cmd := range trusts { + if _, err := os.Stat(filepath.Dir(pathTemplate)); err != nil { + continue + } + + trustPath := fmt.Sprintf(pathTemplate, "bass") + + cert, err := os.ReadFile(BassCAFile) + if err != nil { + return fmt.Errorf("read bass CA: %w", err) + } + + if err := os.WriteFile(trustPath, cert, 0600); err != nil { + return fmt.Errorf("write bass CA to system trust: %w", err) + } + + if _, err := exec.LookPath(cmd[0]); err != nil { + // installer not found; fall back on injecting + break + } + + out, err := exec.Command(cmd[0], cmd[1:]...).CombinedOutput() + if err != nil { + return fmt.Errorf("failed to install cert: %w\n\noutput:\n\n%s", err, string(out)) + } + + return nil + } + + return injectCert() +} + +func injectCert() error { + for _, path := range bundles { + if _, err := os.Stat(path); err != nil { + continue + } + + bundle, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0600) + if err != nil { + return err + } + + cert, err := os.Open(BassCAFile) + if err != nil { + return err + } + + if _, err := bundle.Seek(0, os.SEEK_END); err != nil { + return err + } + + if _, err := bundle.WriteString("\n"); err != nil { + return err + } + + if _, err := io.Copy(bundle, cert); err != nil { + return err + } + + return nil + } + + // this is best-effort + + return nil +} diff --git a/pkg/runtimes/shim/unpack.go b/pkg/runtimes/shim/unpack.go new file mode 100644 index 00000000..2e732146 --- /dev/null +++ b/pkg/runtimes/shim/unpack.go @@ -0,0 +1,174 @@ +package main + +import ( + "archive/tar" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "os" + "path" + "strings" + + "github.com/opencontainers/go-digest" + ispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/opencontainers/umoci/oci/cas" + "github.com/opencontainers/umoci/oci/casext" + "github.com/opencontainers/umoci/oci/layer" +) + +func unpack(args []string) error { + ctx := context.Background() + + if len(args) != 3 { + return fmt.Errorf("usage: unpack ") + } + + archiveSrc := args[0] + fromName := args[1] + rootfsPath := args[2] + + layout, err := openTar(archiveSrc) + if err != nil { + return fmt.Errorf("create layout: %w", err) + } + + defer layout.Close() + + ext := casext.NewEngine(layout) + + mspec, err := loadManifest(ctx, ext, fromName) + if err != nil { + return err + } + + err = layer.UnpackRootfs(context.Background(), ext, rootfsPath, mspec, &layer.UnpackOptions{}) + if err != nil { + return fmt.Errorf("unpack rootfs: %w", err) + } + + return nil +} + +func openTar(tarPath string) (cas.Engine, error) { + archive, err := os.Open(tarPath) + if err != nil { + return nil, err + } + + return &tarEngine{archive}, nil +} + +// tarEngine implements a read-only cas.Engine backed by a .tar archive. +type tarEngine struct { + archive *os.File +} + +func (engine *tarEngine) PutBlob(ctx context.Context, reader io.Reader) (digest.Digest, int64, error) { + return "", 0, fmt.Errorf("PutBlob: %w", cas.ErrNotImplemented) +} + +func (engine *tarEngine) GetBlob(ctx context.Context, dig digest.Digest) (io.ReadCloser, error) { + r, err := engine.open(path.Join("blobs", dig.Algorithm().String(), dig.Encoded())) + if err != nil { + return nil, err + } + + return io.NopCloser(r), nil +} + +func (engine *tarEngine) StatBlob(ctx context.Context, dig digest.Digest) (bool, error) { + _, err := engine.open(path.Join("blobs", dig.Algorithm().String(), dig.Encoded())) + if err != nil { + if errors.Is(err, cas.ErrNotExist) { + return false, nil + } + + return false, err + } + + return true, nil +} + +func (engine *tarEngine) PutIndex(ctx context.Context, index ispec.Index) error { + return fmt.Errorf("PutIndex: %w", cas.ErrNotImplemented) +} + +func (engine *tarEngine) GetIndex(ctx context.Context) (ispec.Index, error) { + var idx ispec.Index + r, err := engine.open("index.json") + if err != nil { + return ispec.Index{}, err + } + + err = json.NewDecoder(r).Decode(&idx) + if err != nil { + return ispec.Index{}, err + } + + return idx, nil +} + +func (engine *tarEngine) open(p string) (io.Reader, error) { + _, err := engine.archive.Seek(0, 0) + if err != nil { + return nil, fmt.Errorf("seek: %w", err) + } + + tr := tar.NewReader(engine.archive) + + for { + hdr, err := tr.Next() + if err != nil { + if err == io.EOF { + return nil, fmt.Errorf("open %s: %w", p, cas.ErrNotExist) + } + + return nil, err + } + + if path.Clean(hdr.Name) == p { + return tr, nil + } + } +} + +func (engine *tarEngine) DeleteBlob(ctx context.Context, digest digest.Digest) (err error) { + return fmt.Errorf("DeleteBlob: %w", cas.ErrNotImplemented) +} + +func (engine *tarEngine) ListBlobs(ctx context.Context) ([]digest.Digest, error) { + _, err := engine.archive.Seek(0, 0) + if err != nil { + return nil, fmt.Errorf("seek: %w", err) + } + + tr := tar.NewReader(engine.archive) + + var digs []digest.Digest + for { + hdr, err := tr.Next() + if err != nil { + if err == io.EOF { + break + } + + return nil, fmt.Errorf("next: %w", err) + } + + if strings.HasPrefix(path.Clean(hdr.Name), "blobs/") { + dir, encoded := path.Split(hdr.Name) + _, alg := path.Split(dir) + digs = append(digs, digest.NewDigestFromEncoded(digest.Algorithm(alg), encoded)) + } + } + + return digs, nil +} + +func (engine *tarEngine) Clean(ctx context.Context) error { return nil } + +func (engine *tarEngine) Close() error { + return engine.archive.Close() +} diff --git a/pkg/runtimes/suite.go b/pkg/runtimes/suite.go index 50281d3e..68a14bcd 100644 --- a/pkg/runtimes/suite.go +++ b/pkg/runtimes/suite.go @@ -210,14 +210,28 @@ func Suite(t *testing.T, pool bass.RuntimePool) { File: "addrs.bass", Result: bass.String("hello, world!"), }, + { + File: "tls.bass", + Result: bass.Bool(true), + }, } { test := test t.Run(filepath.Base(test.File), func(t *testing.T) { is := is.New(t) t.Parallel() + ctx := context.Background() + + // set a reasonable timeout so we get a more descriptive failure than the + // global go test timeout + // + // ideally this would be even lower but we should account for slow + // networks for image fetching/etc. + ctx, stop := context.WithTimeout(ctx, 5*time.Minute) + defer stop() + displayBuf := new(bytes.Buffer) - ctx := bass.WithTrace(context.Background(), &bass.Trace{}) + ctx = bass.WithTrace(ctx, &bass.Trace{}) ctx = ioctx.StderrToContext(ctx, displayBuf) res, err := RunTest(ctx, t, pool, test.File, nil) t.Logf("progress:\n%s", displayBuf.String()) @@ -331,6 +345,8 @@ func RunTest(ctx context.Context, t *testing.T, pool bass.RuntimePool, file stri Stdout: bass.NewSink(bass.NewJSONSink("stdout", vtx.Stdout())), }) + scope.Set("*memos*", bass.NewHostPath("./testdata/", bass.ParseFileOrDirPath("bass.lock"))) + source := bass.NewFSPath(testdata.FS, bass.ParseFileOrDirPath(file)) res, err := bass.EvalFSFile(ctx, scope, source) diff --git a/pkg/runtimes/testdata/bass.lock b/pkg/runtimes/testdata/bass.lock index f4b123b1..fe888c1a 100644 --- a/pkg/runtimes/testdata/bass.lock +++ b/pkg/runtimes/testdata/bass.lock @@ -92,5 +92,257 @@ memos: { } } } + 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: "nixery.dev/simple-http-server" + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } + } + } + } + } + } + output: { + object: { + bindings: { + symbol: "repository" + value: { + string: { + value: "nixery.dev/simple-http-server" + } + } + } + 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:13a32cf276567978ad829355e336174aa107f29e7cf078a25ec30ba1d1bc8d5d" + } + } + } + } + } + } + results: { + input: { + array: { + values: { + object: { + bindings: { + symbol: "platform" + value: { + object: { + bindings: { + symbol: "os" + value: { + string: { + value: "linux" + } + } + } + } + } + } + bindings: { + symbol: "repository" + value: { + string: { + value: "nixery.dev/curl" + } + } + } + bindings: { + symbol: "tag" + value: { + string: { + value: "latest" + } + } + } + } + } + } + } + output: { + object: { + bindings: { + symbol: "repository" + value: { + string: { + value: "nixery.dev/curl" + } + } + } + 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:ea6ad85d3dfbf10668b325aa4382eea4859df41cdd160d7204bd9200a698b24d" + } + } + } + } + } + } } } diff --git a/pkg/runtimes/testdata/tls.bass b/pkg/runtimes/testdata/tls.bass new file mode 100644 index 00000000..cc5187b5 --- /dev/null +++ b/pkg/runtimes/testdata/tls.bass @@ -0,0 +1,32 @@ +(use (.regexp)) + +(def config + {:version "0.1" + :http {:addr "0.0.0.0:5000" + :tls {:certificate "/registry.crt" + :key "/registry.key"}} + :storage {:filesystem {:rootdirectory "/var/lib/registry"}} + :proxy {:remoteurl "https://registry-1.docker.io"}}) + +(def mirror + (-> ($ registry serve (mkfile ./config.yml (json config))) + (with-image (linux/registry)) + (with-mount (cache-dir "registry-mirror") /var/lib/registry/) + (with-tls /registry.crt /registry.key) + (with-port :http 5000))) + +; buildkit -> thunk TLS +(def image + (resolve {:platform {:os "linux"} + :repository (addr mirror :http "$host:$port/library/alpine") + :tag "latest"})) + +; thunk -> thunk TLS +(def manifest + (from image + ($ wget -O- + (addr mirror :http + "https://$host:$port/v2/library/alpine/manifests/latest")))) + +(= (-> manifest (read :json) next :tag) + "latest") diff --git a/pkg/runtimes/testdata/tls/.gitignore b/pkg/runtimes/testdata/tls/.gitignore new file mode 100644 index 00000000..f4107977 --- /dev/null +++ b/pkg/runtimes/testdata/tls/.gitignore @@ -0,0 +1,5 @@ +* +!bass.crt +!bass.key +!.gitignore +!fs.go diff --git a/pkg/runtimes/testdata/tls/bass.crt b/pkg/runtimes/testdata/tls/bass.crt new file mode 100644 index 00000000..7284f910 --- /dev/null +++ b/pkg/runtimes/testdata/tls/bass.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDQDCCAiigAwIBAgIBATANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJDQTEQ +MA4GA1UECBMHT250YXJpbzEQMA4GA1UEBxMHVG9yb250bzENMAsGA1UEAxMEYmFz +czAeFw0yMjA4MjYwMTUwNTNaFw0yMjEwMjkwMjAwNTNaMEAxCzAJBgNVBAYTAkNB +MRAwDgYDVQQIEwdPbnRhcmlvMRAwDgYDVQQHEwdUb3JvbnRvMQ0wCwYDVQQDEwRi +YXNzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs1YAdwMgr4MJQwa8 +c3i12yWxdbw0DjjZqDDN59CUpyGGVAk91S0IHSmsBjSvMZmH/tqEJQO1e6HK5eY/ +Ziy0ETbrVYhGtEPhCRVZAM7wVcqI2ZCY0lSSGhgD0/dlY0OW/DaxOTg/QI0UUQpX +3QJ8Jld4gDJLls6NFyu3o4N0Afag2ch6bpvSVX4p0dHYmovY2FTABEIFyJZ+LWsT +QYcL3jCNWVo8bNjGkKUjxqbfuCOiNx4gSyRgkZVvdv0e/K/bM6vC7dlKKVC2OSp0 +YGfLma1PpyqMjN91xVhg6CAutS+oV5YPU20vr9JC4qHgK6c5TFfRPae8aNjd+1sw +IyApnQIDAQABo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIB +ADAdBgNVHQ4EFgQU1oiylsE9jj057p2W6pR/UqyGtoQwDQYJKoZIhvcNAQELBQAD +ggEBADTz1bKkERi8ZlOPvzXbDjL4KMU2ziMbphhN7o8jc7rrMHv1pb5M+33ZyB3h +JHUs3yKvMfEUO5u7vju5L1YTS0DkS9950F43+YnNtPqcvjRR5FfUH8zKFPajY7Ny +c4muQ5uX8PtF/C+gaNmAIT75l7J10YB/KssdUcjITZNwk7enfbrutil38wT1vNWt +UG5uh5O9V9qmQANwmEPex1ByfpL48euwykWSvFhgbpMW49v3Mo+i/vdm8MpIWkUL +aKVvsKgpowNYM8IQSf9v/ibvyFaLmMeYMDnMyJEgyR84KHxftmFWXYTybk/JAFen +9tH1Mg0hyeUDcQIgukWwg565N3w= +-----END CERTIFICATE----- diff --git a/pkg/runtimes/testdata/tls/bass.key b/pkg/runtimes/testdata/tls/bass.key new file mode 100644 index 00000000..0909c619 --- /dev/null +++ b/pkg/runtimes/testdata/tls/bass.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAs1YAdwMgr4MJQwa8c3i12yWxdbw0DjjZqDDN59CUpyGGVAk9 +1S0IHSmsBjSvMZmH/tqEJQO1e6HK5eY/Ziy0ETbrVYhGtEPhCRVZAM7wVcqI2ZCY +0lSSGhgD0/dlY0OW/DaxOTg/QI0UUQpX3QJ8Jld4gDJLls6NFyu3o4N0Afag2ch6 +bpvSVX4p0dHYmovY2FTABEIFyJZ+LWsTQYcL3jCNWVo8bNjGkKUjxqbfuCOiNx4g +SyRgkZVvdv0e/K/bM6vC7dlKKVC2OSp0YGfLma1PpyqMjN91xVhg6CAutS+oV5YP +U20vr9JC4qHgK6c5TFfRPae8aNjd+1swIyApnQIDAQABAoIBAQCxkt3g+lLaF1kL +alcdy4/e0GL4noO49WfoF3M7MBiRqSt2eLQmKnHXVpUEjBRRe6Hio4KnmBWStrDO +lf9+75LZXNUHm2nPQ0tHkEDSARaPDH4XWAtKcP0+IztfHp/g+2M8l/dCHkTbaRaN +7Dz2FWjTGleyMJsSV7HzGJG8sgQjj+TJfjFprLPdiNcS7/Ehs2R081o3eyc1eFox +PkLy9zmQz7sWlaJ7PT3VO2ep94tDllsA86Bx2D4lqxOTvUkvIfxa7S6x5Ornvbi6 +v5YMbg4HdaDr1IaR37D8ROzWmenKscsIbDuCJlWTtLNN++C6cWfd1gqTl6E3yS0F +QwgraXuhAoGBAMPcSGOk3sSuXz1jSVHPBzWNU6AzOyJa1dGK2Q6iPJCvmpRM1r2w +b7ZBZvXlXB6xTXRAABTR+woWobD48R+e5zfM+a9hZwmN5w7FiOKHlVB9UtkSf8Et +m80Uv4NIw0xZ4fytrJ2/xJ/KK2yKZgjKl+h8RiRxPKQXDKV9upNfYpwVAoGBAOpm +zJcH+0ZlaCnH2Nd0eHmV53EkdhUGtEjaWarksJ4wem333enGY2cEjllZGXgBS6Ro +TbTJ9poNxEcGKQNSTJ9ryVNSjTmOCnDU+L8DP/GXbfAdd/RGmnTXaG/gLvGS6sWH +qiixNfJJvfVokrLT7rWa/XKUjpSjo2MfRI4cfdFpAoGAYt7BYCOrHMgVZczIB1cm +AX+NNnKGKGqIQ1X/CmcVgchTlQdQ48K8MdnEGt8kaI4CVmu0Xs49FrOj/c09E0RI +3h9H76OQuv76I7fNyOS+mDobZ17yRNc8LgOKRcCmbdV1wfL+D0ft/ue0kf8vUMLM +ely5n83V2dOU27mjRJ/DDJ0CgYEAsiM57LXmItPCW65Df0pGnLBt2bCKBOS5cnxu +lM+D4lSZVqV/AsEAnjP6MrDiCC+D2whhtbmfLei0d/2Ygau0C5wQvsAID+uAx8sy +14eSuvoIVOkwVnapv45NEmjfhDvRLBk0GgTDKMUeFjlI85rY2S9W2hNIYHIUI6qJ +oS7J97ECgYEAq3+9kljKyFwDLZMbCDmx4oWH0ftbgmkQUQjTgbiXRXvBjDgxBgAw +jmUefppEcX9W6IERSL7i8a5lWIy/h9Vpo3ulG890jvfyr0AZ0AguygTbp1zR1OsF +uAMYlpLKHSKidWevu4+k1i76qzToaXxkgi2nPW9d8eJWzp0HQ2qEJyQ= +-----END RSA PRIVATE KEY----- diff --git a/pkg/runtimes/testdata/tls/fs.go b/pkg/runtimes/testdata/tls/fs.go new file mode 100644 index 00000000..6fd8bafc --- /dev/null +++ b/pkg/runtimes/testdata/tls/fs.go @@ -0,0 +1,6 @@ +package tls + +import _ "embed" + +//go:embed bass.crt +var TestCert []byte diff --git a/pkg/runtimes/util/buildkitd/buildkitd.go b/pkg/runtimes/util/buildkitd/buildkitd.go index ebc1a2d9..9dac421d 100644 --- a/pkg/runtimes/util/buildkitd/buildkitd.go +++ b/pkg/runtimes/util/buildkitd/buildkitd.go @@ -1,34 +1,46 @@ package buildkitd import ( + "archive/tar" + "bytes" "context" "errors" "fmt" + "os" "os/exec" "strings" "time" "github.com/adrg/xdg" + "github.com/docker/docker/libnetwork/resolvconf" "github.com/gofrs/flock" _ "github.com/moby/buildkit" bk "github.com/moby/buildkit/client" _ "github.com/moby/buildkit/client/connhelper/dockercontainer" // import the container connection driver + "github.com/vito/bass/pkg/basstls" + "github.com/vito/bass/pkg/runtimes/testdata/tls" "github.com/vito/bass/pkg/zapctx" "go.opentelemetry.io/otel" "go.uber.org/zap" ) // bumped by hack/bump-buildkit -const Version = "v0.10.3" +const Version = "master" const ( - image = "basslang/buildkit" containerName = "bass-buildkitd" volumeName = "bass-buildkitd" // Long timeout to allow for slow image pulls of // buildkitd while not blocking for infinity lockTimeout = 10 * time.Minute + + // built from bass/buildkit.bass + image = "basslang/buildkit" + + // coordinate with bass/buildkit.bass + bassGateway = "10.64.0.1" + bassDNS = "dns.bass" ) func Start(ctx context.Context) (string, error) { @@ -98,7 +110,7 @@ func checkBuildkit(ctx context.Context) error { zap.Bool("isActive", config.IsActive), zap.Bool("haveHostNetwork", config.HaveHostNetwork)) - if config.Version != Version || !config.HaveHostNetwork { + if config.Version != Version || config.HaveHostNetwork { logger.Info("upgrading buildkit", zap.String("version", Version), zap.Bool("have host network", config.HaveHostNetwork)) @@ -182,25 +194,43 @@ func installBuildkit(ctx context.Context) error { return err } - // FIXME: buildkitd currently runs without network isolation (--net=host) - // in order for containers to be able to reach localhost. - // This is required for things such as kubectl being able to - // reach a KinD/minikube cluster locally - // #nosec - cmd = exec.CommandContext(ctx, - "docker", + rc, err := resolvconf.Get() + if err != nil { + logger.Error("failed to get resolv.conf", zap.Error(err)) + return fmt.Errorf("get resolv.conf: %w", err) + } + + dockerArgs := []string{ "run", - "--net=host", "-d", "--restart", "always", - "-v", volumeName+":/var/lib/buildkit", + "-v", volumeName + ":/var/lib/buildkit", "--name", containerName, "--privileged", + "--dns", bassGateway, + "--dns-search", bassDNS, + } + + for _, ns := range resolvconf.GetNameservers(rc.Content, resolvconf.IP) { + dockerArgs = append(dockerArgs, "--dns", ns) + } + + for _, domain := range resolvconf.GetSearchDomains(rc.Content) { + dockerArgs = append(dockerArgs, "--dns-search", domain) + } + + for _, opt := range resolvconf.GetOptions(rc.Content) { + dockerArgs = append(dockerArgs, "--dns-option", opt) + } + + dockerArgs = append(dockerArgs, image+":"+Version, "dumb-init", "buildkitd", "--debug", ) + + cmd = exec.CommandContext(ctx, "docker", dockerArgs...) output, err = cmd.CombinedOutput() if err != nil { // If the daemon failed to start because it's already running, @@ -213,9 +243,70 @@ func installBuildkit(ctx context.Context) error { return err } } + + userCert, err := os.ReadFile(basstls.CACert(basstls.DefaultDir)) + if err != nil { + logger.Error("failed to read bass.crt", zap.Error(err)) + return err + } + + err = installCert(ctx, "bass.crt", userCert) + if err != nil { + logger.Error("failed to install bass.crt", zap.Error(err)) + return err + } + + err = installCert(ctx, "bass-tests.crt", tls.TestCert) + if err != nil { + logger.Error("failed to install bass.crt", zap.Error(err)) + return err + } + return waitBuildkit(ctx) } +func installCert(ctx context.Context, name string, cert []byte) error { + // trust the user's bass CA cert so you can fetch images from a registry + // running in a thunk + cmd := exec.CommandContext( + ctx, + "docker", + "cp", + "-", + containerName+":/etc/ssl/certs", + ) + + buf := new(bytes.Buffer) + cmd.Stdin = buf + + tw := tar.NewWriter(buf) + err := tw.WriteHeader(&tar.Header{ + Name: name, + Size: int64(len(cert)), + Mode: 0400, + }) + if err != nil { + return err + } + + _, err = tw.Write(cert) + if err != nil { + return err + } + + err = tw.Flush() + if err != nil { + return err + } + + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("install cert: %w\n\noutput:\n\n%s", err, string(output)) + } + + return nil +} + // waitBuildkit waits for the buildkit daemon to be responsive. func waitBuildkit(ctx context.Context) error { c, err := bk.New(ctx, "docker-container://"+containerName) diff --git a/proto/bass.proto b/proto/bass.proto index 0e58c0b4..6bd04cd1 100644 --- a/proto/bass.proto +++ b/proto/bass.proto @@ -34,6 +34,7 @@ message Thunk { repeated ThunkMount mounts = 8; repeated Binding labels = 9; repeated ThunkPort ports = 10; + ThunkTLS tls = 11; }; message ThunkAddr { @@ -47,6 +48,11 @@ message ThunkPort { int32 port = 2; }; +message ThunkTLS { + FilePath cert = 1; + FilePath key = 2; +}; + message ThunkImage { oneof image { ImageRef ref = 1;