diff --git a/client/build_test.go b/client/build_test.go index 4e183eff8e40..07a343b531fd 100644 --- a/client/build_test.go +++ b/client/build_test.go @@ -18,6 +18,7 @@ import ( gatewayapi "github.com/moby/buildkit/frontend/gateway/pb" "github.com/moby/buildkit/identity" "github.com/moby/buildkit/session" + "github.com/moby/buildkit/session/networks" "github.com/moby/buildkit/session/secrets/secretsprovider" "github.com/moby/buildkit/session/sshforward/sshprovider" "github.com/moby/buildkit/solver/errdefs" @@ -45,6 +46,7 @@ func TestClientGatewayIntegration(t *testing.T) { testClientGatewayContainerPID1Exit, testClientGatewayContainerMounts, testClientGatewayContainerSecretEnv, + testClientGatewayContainerNetworkConfig, testClientGatewayContainerPID1Tty, testClientGatewayContainerCancelPID1Tty, testClientGatewayContainerExecTty, @@ -913,6 +915,101 @@ func testClientGatewayContainerSecretEnv(t *testing.T, sb integration.Sandbox) { checkAllReleasable(t, c, sb, true) } +func testClientGatewayContainerNetworkConfig(t *testing.T, sb integration.Sandbox) { + requiresLinux(t) + + ctx := sb.Context() + + c, err := New(ctx, sb.Address()) + require.NoError(t, err) + defer c.Close() + + product := "buildkit_test" + + outBuf := new(bytes.Buffer) + b := func(ctx context.Context, c client.Client) (*client.Result, error) { + mounts := map[string]llb.State{ + "/": llb.Image("busybox:latest"), + } + + var containerMounts []client.Mount + for mountpoint, st := range mounts { + def, err := st.Marshal(ctx) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal state") + } + + r, err := c.Solve(ctx, client.SolveRequest{ + Definition: def.ToPB(), + }) + if err != nil { + return nil, errors.Wrap(err, "failed to solve") + } + containerMounts = append(containerMounts, client.Mount{ + Dest: mountpoint, + MountType: pb.MountType_BIND, + Ref: r.Ref, + }) + } + + ctr, err := c.NewContainer(ctx, client.NewContainerRequest{ + Mounts: containerMounts, + NetworkConfigID: "my-network", + }) + if err != nil { + return nil, err + } + + pid, err := ctr.Start(ctx, client.StartRequest{ + Args: []string{"sh", "-c", "echo hosts; cat /etc/hosts; echo resolv; cat /etc/resolv.conf"}, + Stdout: &nopCloser{outBuf}, + }) + require.NoError(t, err) + err = pid.Wait() + require.NoError(t, err) + + return &client.Result{}, ctr.Release(ctx) + } + + _, err = c.Build(ctx, SolveOpt{ + Session: []session.Attachable{ + networks.NewConfigProvider(func(id string) *networks.Config { + switch id { + case "my-network": + return &networks.Config{ + Dns: &networks.DNSConfig{ + Nameservers: []string{"1.1.1.1"}, + SearchDomains: []string{"zombo.com"}, + Options: []string{"ndots:999"}, + }, + IpHosts: []*networks.IPHosts{ + { + Ip: "1.2.3.4", + Hosts: []string{"example.com"}, + }, + }, + } + default: + panic("unknown network ID") + } + }), + }, + }, product, b, nil) + require.NoError(t, err) + + require.Equal(t, `hosts +127.0.0.1 localhost buildkitsandbox +::1 localhost ip6-localhost ip6-loopback +1.2.3.4 example.com +resolv +search zombo.com +nameserver 1.1.1.1 +options ndots:999 +`, outBuf.String()) + + checkAllReleasable(t, c, sb, true) +} + // testClientGatewayContainerPID1Tty is testing that we can get a tty via // a container pid1, executor.Run func testClientGatewayContainerPID1Tty(t *testing.T, sb integration.Sandbox) { diff --git a/client/client_test.go b/client/client_test.go index b28dbbe64832..3257d96f7c9d 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -2,6 +2,7 @@ package client import ( "archive/tar" + "bufio" "bytes" "compress/gzip" "context" @@ -46,6 +47,7 @@ import ( gatewaypb "github.com/moby/buildkit/frontend/gateway/pb" "github.com/moby/buildkit/identity" "github.com/moby/buildkit/session" + "github.com/moby/buildkit/session/networks" "github.com/moby/buildkit/session/secrets/secretsprovider" "github.com/moby/buildkit/session/sshforward/sshprovider" "github.com/moby/buildkit/solver/errdefs" @@ -205,6 +207,7 @@ func TestIntegration(t *testing.T) { testMultipleRecordsWithSameLayersCacheImportExport, testExportLocalNoPlatformSplit, testExportLocalNoPlatformSplitOverwrite, + testExecNetworkConfig, ) } @@ -242,6 +245,8 @@ func testIntegration(t *testing.T, funcs ...func(t *testing.T, sb integration.Sa integration.Run(t, integration.TestFuncs( testBridgeNetworkingDNSNoRootless, + testBridgeNetworkingDNSGitNoRootless, + testBridgeNetworkingDNSHTTPNoRootless, ), mirrors, integration.WithMatrix("netmode", map[string]interface{}{ @@ -359,6 +364,270 @@ func testBridgeNetworkingDNSNoRootless(t *testing.T, sb integration.Sandbox) { require.NoError(t, err) } +func testBridgeNetworkingDNSGitNoRootless(t *testing.T, sb integration.Sandbox) { + integration.CheckFeatureCompat(t, sb, integration.FeatureCNINetwork) + if os.Getenv("BUILDKIT_RUN_NETWORK_INTEGRATION_TESTS") == "" { + t.SkipNow() + } + + c, err := New(sb.Context(), sb.Address()) + require.NoError(t, err) + defer c.Close() + + serverBase := llb.Image("alpine:latest"). + Run(llb.Shlexf(`apk add git git-daemon`)). + File( + llb.Mkdir("/root/repo", 0755). + Mkfile("/root/repo/some-file", 0644, []byte(`hello`)), + ). + File(llb.Mkfile("/start.sh", 0755, []byte(`#!/bin/sh + +set -e -u -x + +cd /root + +git config --global user.email "root@localhost" +git config --global user.name "Test User" +git config --global init.defaultBranch main + +mkdir srv + +cd repo + git init + git add * + git commit -m "init" +cd .. + +cd srv + git clone --bare ../repo repo.git +cd .. + +git daemon --verbose --export-all --base-path=/root/srv +`))) + + myDomain := "mydomain" + testGit := func(ctx context.Context, gw gateway.Client) (*gateway.Result, error) { + def, err := serverBase.Marshal(ctx) + if err != nil { + return nil, err + } + + res, err := gw.Solve(ctx, gateway.SolveRequest{ + Definition: def.ToPB(), + }) + if err != nil { + return nil, err + } + + gitHost := identity.NewID() + gitCtr, err := gw.NewContainer(ctx, gateway.NewContainerRequest{ + Mounts: []gateway.Mount{ + { + Dest: "/", + MountType: pb.MountType_BIND, + Ref: res.Ref, + }, + }, + Hostname: gitHost + "." + myDomain, + }) + if err != nil { + return nil, err + } + defer gitCtr.Release(context.Background()) + + stderrR, stderrW := io.Pipe() + + proc, err := gitCtr.Start(ctx, gateway.StartRequest{ + Args: []string{"/start.sh"}, + Stderr: stderrW, + }) + if err != nil { + return nil, err + } + defer proc.Signal(ctx, syscall.SIGKILL) + + scan := bufio.NewScanner(stderrR) + for scan.Scan() { + line := scan.Text() + t.Log(line) + if strings.Contains(line, "Ready to rumble") { + t.Logf("git server is ready") + break + } + } + + gitSt := llb.Git( + "git://"+gitHost+"/repo.git", + "main", + llb.WithNetworkConfig("git-client"), + ) + + def, err = gitSt.Marshal(ctx) + if err != nil { + return nil, err + } + + res, err = gw.Solve(ctx, gateway.SolveRequest{ + Definition: def.ToPB(), + Evaluate: true, + }) + if err != nil { + return nil, err + } + + _, err = res.Ref.StatFile(ctx, gateway.StatRequest{ + Path: "some-file", + }) + if err != nil { + return nil, err + } + + return gateway.NewResult(), nil + } + + _, err = c.Build(sb.Context(), SolveOpt{ + Session: []session.Attachable{ + networks.NewConfigProvider(func(id string) *networks.Config { + switch id { + case "git-client": + return &networks.Config{ + Dns: &networks.DNSConfig{ + SearchDomains: []string{myDomain}, + }, + } + default: + panic("unknown network: " + id) + } + }), + }, + }, "", testGit, nil) + require.NoError(t, err) +} + +func testBridgeNetworkingDNSHTTPNoRootless(t *testing.T, sb integration.Sandbox) { + integration.CheckFeatureCompat(t, sb, integration.FeatureCNINetwork) + if os.Getenv("BUILDKIT_RUN_NETWORK_INTEGRATION_TESTS") == "" { + t.SkipNow() + } + + c, err := New(sb.Context(), sb.Address()) + require.NoError(t, err) + defer c.Close() + + serverBase := llb.Image("alpine:latest"). + Run(llb.Shlexf(`apk add python3`)). + File( + llb.Mkdir("/root/www", 0755). + Mkfile("/root/www/some-file", 0644, []byte(`hello`)), + ). + File(llb.Mkfile("/start.sh", 0755, []byte(`#!/bin/sh + +set -e -u -x + +cd /root/www + +python -m http.server 8000 +`))) + + myDomain := "mydomain" + testGit := func(ctx context.Context, gw gateway.Client) (*gateway.Result, error) { + def, err := serverBase.Marshal(ctx) + if err != nil { + return nil, err + } + + res, err := gw.Solve(ctx, gateway.SolveRequest{ + Definition: def.ToPB(), + }) + if err != nil { + return nil, err + } + + httpHost := identity.NewID() + httpCtr, err := gw.NewContainer(ctx, gateway.NewContainerRequest{ + Mounts: []gateway.Mount{ + { + Dest: "/", + MountType: pb.MountType_BIND, + Ref: res.Ref, + }, + }, + Hostname: httpHost + "." + myDomain, + }) + if err != nil { + return nil, err + } + defer httpCtr.Release(context.Background()) + + stdoutR, stdoutW := io.Pipe() + + proc, err := httpCtr.Start(ctx, gateway.StartRequest{ + Args: []string{"/start.sh"}, + Stdout: stdoutW, + Tty: true, + }) + if err != nil { + return nil, err + } + defer proc.Signal(ctx, syscall.SIGKILL) + + scan := bufio.NewScanner(stdoutR) + for scan.Scan() { + line := scan.Text() + t.Logf("from server: %s", line) + if strings.Contains(line, "Serving HTTP") { + t.Logf("HTTP server is ready") + break + } + } + + httpSt := llb.HTTP( + "http://"+httpHost+":8000/some-file", + llb.WithNetworkConfig("http-client"), + ) + + def, err = httpSt.Marshal(ctx) + if err != nil { + return nil, err + } + + res, err = gw.Solve(ctx, gateway.SolveRequest{ + Definition: def.ToPB(), + Evaluate: true, + }) + if err != nil { + return nil, err + } + + _, err = res.Ref.StatFile(ctx, gateway.StatRequest{ + Path: "some-file", + }) + if err != nil { + return nil, err + } + + return gateway.NewResult(), nil + } + + _, err = c.Build(sb.Context(), SolveOpt{ + Session: []session.Attachable{ + networks.NewConfigProvider(func(id string) *networks.Config { + switch id { + case "http-client": + return &networks.Config{ + Dns: &networks.DNSConfig{ + SearchDomains: []string{myDomain}, + }, + } + default: + panic("unknown network: " + id) + } + }), + }, + }, "", testGit, nil) + require.NoError(t, err) +} + func testHostNetworking(t *testing.T, sb integration.Sandbox) { if os.Getenv("BUILDKIT_RUN_NETWORK_INTEGRATION_TESTS") == "" { t.SkipNow() @@ -9627,3 +9896,67 @@ func testClientCustomGRPCOpts(t *testing.T, sb integration.Sandbox) { require.Contains(t, interceptedMethods, "/moby.buildkit.v1.Control/Solve") } + +func testExecNetworkConfig(t *testing.T, sb integration.Sandbox) { + c, err := New(sb.Context(), sb.Address()) + require.NoError(t, err) + defer c.Close() + + st := llb.Image("busybox:latest"). + Run( + llb.Shlex(`sh -c 'cp /etc/hosts /out/hosts && cp /etc/resolv.conf /out/resolv.conf'`), + llb.WithNetworkConfig("my-network"), + ) + + out := st.AddMount("/out", llb.Scratch()) + def, err := out.Marshal(sb.Context()) + require.NoError(t, err) + + destDir := t.TempDir() + + _, err = c.Solve(sb.Context(), def, SolveOpt{ + Exports: []ExportEntry{ + { + Type: ExporterLocal, + OutputDir: destDir, + }, + }, + Session: []session.Attachable{ + networks.NewConfigProvider(func(id string) *networks.Config { + switch id { + case "my-network": + return &networks.Config{ + Dns: &networks.DNSConfig{ + Nameservers: []string{"1.1.1.1"}, + SearchDomains: []string{"zombo.com"}, + Options: []string{"ndots:999"}, + }, + IpHosts: []*networks.IPHosts{ + { + Ip: "1.2.3.4", + Hosts: []string{"example.com"}, + }, + }, + } + default: + panic("unknown network ID") + } + }), + }, + }, nil) + require.NoError(t, err) + + resolv, err := os.ReadFile(filepath.Join(destDir, "resolv.conf")) + require.NoError(t, err) + require.Equal(t, `search zombo.com +nameserver 1.1.1.1 +options ndots:999 +`, string(resolv)) + + hosts, err := os.ReadFile(filepath.Join(destDir, "hosts")) + require.NoError(t, err) + require.Equal(t, `127.0.0.1 localhost buildkitsandbox +::1 localhost ip6-localhost ip6-loopback +1.2.3.4 example.com +`, string(hosts)) +} diff --git a/client/llb/exec.go b/client/llb/exec.go index 0eed6774c2eb..c27b3595393e 100644 --- a/client/llb/exec.go +++ b/client/llb/exec.go @@ -58,6 +58,7 @@ type ExecOp struct { isValidated bool secrets []SecretInfo ssh []SSHInfo + netConfigID NetworkConfigID } func (e *ExecOp) AddMount(target string, source Output, opt ...MountOption) Output { @@ -413,6 +414,11 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, [] peo.Mounts = append(peo.Mounts, pm) } + if e.netConfigID != "" { + addCap(&e.constraints, pb.CapNetworkConfigs) + peo.NetworkConfigID = e.netConfigID.String() + } + dt, err := pop.Marshal() if err != nil { return "", nil, nil, nil, err @@ -723,12 +729,13 @@ func WithProxy(ps ProxyEnv) RunOption { type ExecInfo struct { constraintsWrapper - State State - Mounts []MountInfo - ReadonlyRootFS bool - ProxyEnv *ProxyEnv - Secrets []SecretInfo - SSH []SSHInfo + State State + Mounts []MountInfo + ReadonlyRootFS bool + ProxyEnv *ProxyEnv + Secrets []SecretInfo + SSH []SSHInfo + NetworkConfigID NetworkConfigID } type MountInfo struct { diff --git a/client/llb/source.go b/client/llb/source.go index fa1096a67c23..556870f25039 100644 --- a/client/llb/source.go +++ b/client/llb/source.go @@ -309,6 +309,10 @@ func Git(remote, ref string, opts ...GitOption) State { } addCap(&gi.Constraints, pb.CapSourceGitMountSSHSock) } + if gi.NetworkConfigID != "" { + attrs[pb.AttrNetworkConfigID] = gi.NetworkConfigID.String() + addCap(&gi.Constraints, pb.CapNetworkConfigs) + } addCap(&gi.Constraints, pb.CapSourceGit) @@ -333,6 +337,7 @@ type GitInfo struct { addAuthCap bool KnownSSHHosts string MountSSHSock string + NetworkConfigID NetworkConfigID } func KeepGitDir() GitOption { @@ -583,6 +588,10 @@ func HTTP(url string, opts ...HTTPOption) State { attrs[pb.AttrHTTPGID] = strconv.Itoa(hi.GID) addCap(&hi.Constraints, pb.CapSourceHTTPUIDGID) } + if hi.NetworkConfigID != "" { + attrs[pb.AttrNetworkConfigID] = hi.NetworkConfigID.String() + addCap(&hi.Constraints, pb.CapNetworkConfigs) + } addCap(&hi.Constraints, pb.CapSourceHTTP) source := NewSource(url, attrs, hi.Constraints) @@ -591,11 +600,12 @@ func HTTP(url string, opts ...HTTPOption) State { type HTTPInfo struct { constraintsWrapper - Checksum digest.Digest - Filename string - Perm int - UID int - GID int + Checksum digest.Digest + Filename string + Perm int + UID int + GID int + NetworkConfigID NetworkConfigID } type HTTPOption interface { @@ -633,6 +643,34 @@ func Chown(uid, gid int) HTTPOption { }) } +type NetworkConfigID string + +func (id NetworkConfigID) String() string { + return string(id) +} + +func WithNetworkConfig(id string) NetworkConfigID { + return NetworkConfigID(id) +} + +var _ GitOption = NetworkConfigID("") + +func (id NetworkConfigID) SetGitOption(i *GitInfo) { + i.NetworkConfigID = id +} + +var _ HTTPOption = NetworkConfigID("") + +func (id NetworkConfigID) SetHTTPOption(i *HTTPInfo) { + i.NetworkConfigID = id +} + +var _ RunOption = NetworkConfigID("") + +func (id NetworkConfigID) SetRunOption(i *ExecInfo) { + i.NetworkConfigID = id +} + func platformSpecificSource(id string) bool { return strings.HasPrefix(id, "docker-image://") || strings.HasPrefix(id, "oci-layout://") } diff --git a/client/llb/state.go b/client/llb/state.go index f15fad87ab21..ddda8880c9c9 100644 --- a/client/llb/state.go +++ b/client/llb/state.go @@ -284,6 +284,7 @@ func (s State) Run(ro ...RunOption) ExecState { } exec.secrets = ei.Secrets exec.ssh = ei.SSH + exec.netConfigID = ei.NetworkConfigID return ExecState{ State: s.WithOutput(exec.Output()), diff --git a/cmd/buildkitd/main.go b/cmd/buildkitd/main.go index 75c4c5628f7d..86a997cf68a6 100644 --- a/cmd/buildkitd/main.go +++ b/cmd/buildkitd/main.go @@ -32,12 +32,12 @@ import ( "github.com/moby/buildkit/client" "github.com/moby/buildkit/cmd/buildkitd/config" "github.com/moby/buildkit/control" - "github.com/moby/buildkit/executor/oci" "github.com/moby/buildkit/frontend" dockerfile "github.com/moby/buildkit/frontend/dockerfile/builder" "github.com/moby/buildkit/frontend/gateway" "github.com/moby/buildkit/frontend/gateway/forwarder" "github.com/moby/buildkit/session" + "github.com/moby/buildkit/session/networks" "github.com/moby/buildkit/solver" "github.com/moby/buildkit/solver/bboltcachestorage" "github.com/moby/buildkit/util/apicaps" @@ -820,10 +820,10 @@ func getBuildkitVersion() client.BuildkitVersion { } } -func getDNSConfig(cfg *config.DNSConfig) *oci.DNSConfig { - var dns *oci.DNSConfig +func getDNSConfig(cfg *config.DNSConfig) *networks.DNSConfig { + var dns *networks.DNSConfig if cfg != nil { - dns = &oci.DNSConfig{ + dns = &networks.DNSConfig{ Nameservers: cfg.Nameservers, Options: cfg.Options, SearchDomains: cfg.SearchDomains, diff --git a/executor/containerdexecutor/executor.go b/executor/containerdexecutor/executor.go index fa578c6d48fa..9ac8a85a421e 100644 --- a/executor/containerdexecutor/executor.go +++ b/executor/containerdexecutor/executor.go @@ -9,6 +9,7 @@ import ( "syscall" "time" + "github.com/moby/buildkit/session/networks" "github.com/moby/buildkit/util/bklog" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -37,7 +38,7 @@ type containerdExecutor struct { root string networkProviders map[pb.NetMode]network.Provider cgroupParent string - dnsConfig *oci.DNSConfig + dnsConfig *networks.DNSConfig running map[string]chan error mu sync.Mutex apparmorProfile string @@ -60,7 +61,7 @@ type OnCreateRuntimer interface { } // New creates a new executor backed by connection to containerd API -func New(client *containerd.Client, root, cgroup string, networkProviders map[pb.NetMode]network.Provider, dnsConfig *oci.DNSConfig, apparmorProfile string, selinux bool, traceSocket string, rootless bool) executor.Executor { +func New(client *containerd.Client, root, cgroup string, networkProviders map[pb.NetMode]network.Provider, dnsConfig *networks.DNSConfig, apparmorProfile string, selinux bool, traceSocket string, rootless bool) executor.Executor { // clean up old hosts/resolv.conf file. ignore errors os.RemoveAll(filepath.Join(root, "hosts")) os.RemoveAll(filepath.Join(root, "resolv.conf")) @@ -104,17 +105,20 @@ func (w *containerdExecutor) Run(ctx context.Context, id string, root executor.M meta := process.Meta - resolvConf, err := oci.GetResolvConf(ctx, w.root, nil, w.dnsConfig) + resolvConf, cleanResolv, err := oci.GetResolvConf(ctx, w.root, nil, w.dnsConfig, meta.DNS) if err != nil { return nil, err } + if cleanResolv != nil { + defer cleanResolv() + } - hostsFile, clean, err := oci.GetHostsFile(ctx, w.root, meta.ExtraHosts, nil, meta.Hostname) + hostsFile, cleanHosts, err := oci.GetHostsFile(ctx, w.root, meta.ExtraHosts, nil, meta.Hostname) if err != nil { return nil, err } - if clean != nil { - defer clean() + if cleanHosts != nil { + defer cleanHosts() } mountable, err := root.Src.Mount(ctx, false) diff --git a/executor/executor.go b/executor/executor.go index 741f347cd9ca..9b4728902e03 100644 --- a/executor/executor.go +++ b/executor/executor.go @@ -7,6 +7,7 @@ import ( "syscall" resourcestypes "github.com/moby/buildkit/executor/resources/types" + "github.com/moby/buildkit/session/networks" "github.com/moby/buildkit/snapshot" "github.com/moby/buildkit/solver/pb" ) @@ -20,6 +21,7 @@ type Meta struct { Tty bool ReadonlyRootFS bool ExtraHosts []HostIP + DNS *networks.DNSConfig Ulimit []*pb.Ulimit CgroupParent string NetMode pb.NetMode diff --git a/executor/oci/resolvconf.go b/executor/oci/resolvconf.go index 9db0b3dfaad6..348cd53edf62 100644 --- a/executor/oci/resolvconf.go +++ b/executor/oci/resolvconf.go @@ -7,6 +7,8 @@ import ( "github.com/docker/docker/libnetwork/resolvconf" "github.com/docker/docker/pkg/idtools" + "github.com/moby/buildkit/identity" + "github.com/moby/buildkit/session/networks" "github.com/moby/buildkit/util/flightcontrol" "github.com/pkg/errors" ) @@ -18,101 +20,110 @@ var lastNotEmpty bool // overridden by tests var resolvconfPath = resolvconf.Path -type DNSConfig struct { - Nameservers []string - Options []string - SearchDomains []string -} +func GetResolvConf(ctx context.Context, stateDir string, idmap *idtools.IdentityMapping, workerDNS, customDNS *networks.DNSConfig) (string, func(), error) { + resolvPath := filepath.Join(stateDir, "resolv.conf") + if customDNS != nil { + resolvPath += "." + identity.NewID() + err := makeResolvFile(resolvPath, stateDir, idmap, customDNS) + if err != nil { + return "", nil, err + } + + return resolvPath, func() { os.Remove(resolvPath) }, nil + } -func GetResolvConf(ctx context.Context, stateDir string, idmap *idtools.IdentityMapping, dns *DNSConfig) (string, error) { - p := filepath.Join(stateDir, "resolv.conf") _, err := g.Do(ctx, stateDir, func(ctx context.Context) (struct{}, error) { - generate := !notFirstRun - notFirstRun = true + return struct{}{}, makeResolvFile(resolvPath, stateDir, idmap, workerDNS) + }) + if err != nil { + return "", nil, err + } + return resolvPath, func() {}, nil +} +func makeResolvFile(resolvPath, stateDir string, idmap *idtools.IdentityMapping, dns *networks.DNSConfig) error { + generate := !notFirstRun + notFirstRun = true + + if !generate { + fi, err := os.Stat(resolvPath) + if err != nil { + if !errors.Is(err, os.ErrNotExist) { + return err + } + generate = true + } if !generate { - fi, err := os.Stat(p) + fiMain, err := os.Stat(resolvconfPath()) if err != nil { if !errors.Is(err, os.ErrNotExist) { - return struct{}{}, err + return err } - generate = true - } - if !generate { - fiMain, err := os.Stat(resolvconfPath()) - if err != nil { - if !errors.Is(err, os.ErrNotExist) { - return struct{}{}, err - } - if lastNotEmpty { - generate = true - lastNotEmpty = false - } - } else { - if fi.ModTime().Before(fiMain.ModTime()) { - generate = true - } + if lastNotEmpty { + generate = true + lastNotEmpty = false + } + } else { + if fi.ModTime().Before(fiMain.ModTime()) { + generate = true } } } + } - if !generate { - return struct{}{}, nil - } - - dt, err := os.ReadFile(resolvconfPath()) - if err != nil && !errors.Is(err, os.ErrNotExist) { - return struct{}{}, err - } + if !generate { + return nil + } - var f *resolvconf.File - tmpPath := p + ".tmp" - if dns != nil { - var ( - dnsNameservers = dns.Nameservers - dnsSearchDomains = dns.SearchDomains - dnsOptions = dns.Options - ) - if len(dns.Nameservers) == 0 { - dnsNameservers = resolvconf.GetNameservers(dt, resolvconf.IP) - } - if len(dns.SearchDomains) == 0 { - dnsSearchDomains = resolvconf.GetSearchDomains(dt) - } - if len(dns.Options) == 0 { - dnsOptions = resolvconf.GetOptions(dt) - } + dt, err := os.ReadFile(resolvconfPath()) + if err != nil && !errors.Is(err, os.ErrNotExist) { + return err + } - f, err = resolvconf.Build(tmpPath, dnsNameservers, dnsSearchDomains, dnsOptions) - if err != nil { - return struct{}{}, err - } - dt = f.Content + var f *resolvconf.File + tmpPath := resolvPath + ".tmp" + if dns != nil { + var ( + dnsNameservers = dns.Nameservers + dnsSearchDomains = dns.SearchDomains + dnsOptions = dns.Options + ) + if len(dns.Nameservers) == 0 { + dnsNameservers = resolvconf.GetNameservers(dt, resolvconf.IP) + } + if len(dns.SearchDomains) == 0 { + dnsSearchDomains = resolvconf.GetSearchDomains(dt) + } + if len(dns.Options) == 0 { + dnsOptions = resolvconf.GetOptions(dt) } - f, err = resolvconf.FilterResolvDNS(dt, true) + f, err = resolvconf.Build(tmpPath, dnsNameservers, dnsSearchDomains, dnsOptions) if err != nil { - return struct{}{}, err + return err } + dt = f.Content + } - if err := os.WriteFile(tmpPath, f.Content, 0644); err != nil { - return struct{}{}, err - } + f, err = resolvconf.FilterResolvDNS(dt, true) + if err != nil { + return err + } - if idmap != nil { - root := idmap.RootPair() - if err := os.Chown(tmpPath, root.UID, root.GID); err != nil { - return struct{}{}, err - } - } + if err := os.WriteFile(tmpPath, f.Content, 0644); err != nil { + return err + } - if err := os.Rename(tmpPath, p); err != nil { - return struct{}{}, err + if idmap != nil { + root := idmap.RootPair() + if err := os.Chown(tmpPath, root.UID, root.GID); err != nil { + return err } - return struct{}{}, nil - }) - if err != nil { - return "", err } - return p, nil + + if err := os.Rename(tmpPath, resolvPath); err != nil { + return err + } + + return nil } diff --git a/executor/oci/resolvconf_test.go b/executor/oci/resolvconf_test.go index d17e706d623f..495c04bc71b9 100644 --- a/executor/oci/resolvconf_test.go +++ b/executor/oci/resolvconf_test.go @@ -5,6 +5,7 @@ import ( "os" "testing" + "github.com/moby/buildkit/session/networks" "github.com/stretchr/testify/require" ) @@ -26,9 +27,61 @@ nameserver 2001:4860:4860::8888 nameserver 2001:4860:4860::8844` ctx := context.Background() - p, err := GetResolvConf(ctx, t.TempDir(), nil, nil) + p, clean, err := GetResolvConf(ctx, t.TempDir(), nil, nil, nil) require.NoError(t, err) + defer clean() b, err := os.ReadFile(p) require.NoError(t, err) - require.Equal(t, string(b), defaultResolvConf) + require.Equal(t, defaultResolvConf, string(b)) +} + +func TestResolvConfOverrides(t *testing.T) { + oldResolvconfPath := resolvconfPath + t.Cleanup(func() { + resolvconfPath = oldResolvconfPath + }) + resolvconfPath = func() string { + return "no-such-file" + } + + workerDNS := &networks.DNSConfig{ + Nameservers: []string{"1.2.3.4"}, + } + + expected := `nameserver 1.2.3.4 +` + + ctx := context.Background() + p, clean, err := GetResolvConf(ctx, t.TempDir(), nil, workerDNS, nil) + require.NoError(t, err) + defer clean() + b, err := os.ReadFile(p) + require.NoError(t, err) + require.Equal(t, expected, string(b)) + clean() + _, err = os.Stat(p) + require.NoError(t, err) // no custom DNS = nothing to clean up + + customDNS := &networks.DNSConfig{ + SearchDomains: []string{"custom-domain"}, + } + + // NB: custom DNS overrides worker DNS completely. in practice it will have + // been merged with the worker DNS already. + expected = `search custom-domain + +nameserver 8.8.8.8 +nameserver 8.8.4.4 +nameserver 2001:4860:4860::8888 +nameserver 2001:4860:4860::8844` + + p, clean, err = GetResolvConf(ctx, t.TempDir(), nil, workerDNS, customDNS) + require.NoError(t, err) + defer clean() + b, err = os.ReadFile(p) + require.NoError(t, err) + require.Equal(t, expected, string(b)) + clean() + _, err = os.Stat(p) + require.ErrorIs(t, err, os.ErrNotExist) } diff --git a/executor/runcexecutor/executor.go b/executor/runcexecutor/executor.go index 9c12996e53da..19d822660132 100644 --- a/executor/runcexecutor/executor.go +++ b/executor/runcexecutor/executor.go @@ -12,6 +12,7 @@ import ( "syscall" "time" + "github.com/moby/buildkit/session/networks" "github.com/moby/buildkit/util/bklog" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -48,7 +49,7 @@ type Opt struct { IdentityMapping *idtools.IdentityMapping // runc run --no-pivot (unrecommended) NoPivot bool - DNS *oci.DNSConfig + DNS *networks.DNSConfig OOMScoreAdj *int ApparmorProfile string SELinux bool @@ -67,7 +68,7 @@ type runcExecutor struct { processMode oci.ProcessMode idmap *idtools.IdentityMapping noPivot bool - dns *oci.DNSConfig + dns *networks.DNSConfig oomScoreAdj *int running map[string]chan error mu sync.Mutex @@ -185,17 +186,20 @@ func (w *runcExecutor) Run(ctx context.Context, id string, root executor.Mount, bklog.G(ctx).Info("enabling HostNetworking") } - resolvConf, err := oci.GetResolvConf(ctx, w.root, w.idmap, w.dns) + resolvConf, cleanResolv, err := oci.GetResolvConf(ctx, w.root, w.idmap, w.dns, meta.DNS) if err != nil { return nil, err } + if cleanResolv != nil { + defer cleanResolv() + } - hostsFile, clean, err := oci.GetHostsFile(ctx, w.root, meta.ExtraHosts, w.idmap, meta.Hostname) + hostsFile, cleanHosts, err := oci.GetHostsFile(ctx, w.root, meta.ExtraHosts, w.idmap, meta.Hostname) if err != nil { return nil, err } - if clean != nil { - defer clean() + if cleanHosts != nil { + defer cleanHosts() } mountable, err := root.Src.Mount(ctx, false) diff --git a/frontend/gateway/client/client.go b/frontend/gateway/client/client.go index 23585de9078e..e4a76ea7e666 100644 --- a/frontend/gateway/client/client.go +++ b/frontend/gateway/client/client.go @@ -37,12 +37,13 @@ type Client interface { // NewContainerRequest encapsulates the requirements for a client to define a // new container, without defining the initial process. type NewContainerRequest struct { - Mounts []Mount - Hostname string - NetMode pb.NetMode - ExtraHosts []*pb.HostIP - Platform *pb.Platform - Constraints *pb.WorkerConstraints + Mounts []Mount + Hostname string + NetMode pb.NetMode + ExtraHosts []*pb.HostIP + Platform *pb.Platform + Constraints *pb.WorkerConstraints + NetworkConfigID string } // Mount allows clients to specify a filesystem mount. A Reference to a diff --git a/frontend/gateway/container/container.go b/frontend/gateway/container/container.go index af6476e7fce2..35e6a445620f 100644 --- a/frontend/gateway/container/container.go +++ b/frontend/gateway/container/container.go @@ -3,6 +3,7 @@ package container import ( "context" "fmt" + "net" "path/filepath" "runtime" "sort" @@ -10,6 +11,7 @@ import ( "sync" "syscall" + "github.com/moby/buildkit/session/networks" "github.com/moby/buildkit/session/secrets" "github.com/moby/buildkit/util/bklog" "github.com/moby/buildkit/util/system" @@ -30,13 +32,14 @@ import ( ) type NewContainerRequest struct { - ContainerID string - NetMode opspb.NetMode - Hostname string - ExtraHosts []executor.HostIP - Mounts []Mount - Platform *opspb.Platform - Constraints *opspb.WorkerConstraints + ContainerID string + NetMode opspb.NetMode + NetworkConfigID string + Hostname string + ExtraHosts []executor.HostIP + Mounts []Mount + Platform *opspb.Platform + Constraints *opspb.WorkerConstraints } // Mount used for the gateway.Container is nearly identical to the client.Mount @@ -60,6 +63,7 @@ func NewContainer(ctx context.Context, w worker.Worker, sm *session.Manager, g s ctr := &gatewayContainer{ id: req.ContainerID, netMode: req.NetMode, + netConfID: req.NetworkConfigID, hostname: req.Hostname, extraHosts: req.ExtraHosts, platform: platform, @@ -289,6 +293,7 @@ type gatewayContainer struct { netMode opspb.NetMode hostname string extraHosts []executor.HostIP + netConfID string platform opspb.Platform rootFS executor.Mount mounts []executor.Mount @@ -339,6 +344,32 @@ func (gwCtr *gatewayContainer) Start(ctx context.Context, req client.StartReques } procInfo.Meta.Env = append(procInfo.Meta.Env, secretEnv...) + netCfg, err := gwCtr.loadNetworkConfig(ctx) + if err != nil { + return nil, err + } + if netCfg != nil { + for _, ipHosts := range netCfg.IpHosts { + for _, host := range ipHosts.Hosts { + ip := net.ParseIP(ipHosts.Ip) + if ip == nil { + return nil, errors.Errorf("invalid ip %q", ipHosts.Ip) + } + procInfo.Meta.ExtraHosts = append(procInfo.Meta.ExtraHosts, executor.HostIP{ + Host: host, + IP: ip, + }) + } + } + if netCfg.Dns != nil { + procInfo.Meta.DNS = &networks.DNSConfig{ + Nameservers: netCfg.Dns.Nameservers, + SearchDomains: netCfg.Dns.SearchDomains, + Options: netCfg.Dns.Options, + } + } + } + // mark that we have started on the first call to execProcess for this // container, so that future calls will call Exec rather than Run gwCtr.mu.Lock() @@ -405,6 +436,23 @@ func (gwCtr *gatewayContainer) loadSecretEnv(ctx context.Context, secretEnv []*p return out, nil } +func (gwCtr *gatewayContainer) loadNetworkConfig(ctx context.Context) (*networks.Config, error) { + id := gwCtr.netConfID + if id == "" { + return nil, nil + } + cfg := &networks.Config{} + err := gwCtr.sm.Any(ctx, gwCtr.group, func(ctx context.Context, _ string, caller session.Caller) error { + var err error + cfg, err = networks.MergeConfig(ctx, caller, cfg, id) + return err + }) + if err != nil { + return nil, err + } + return cfg, nil +} + func (gwCtr *gatewayContainer) Release(ctx context.Context) error { gwCtr.mu.Lock() defer gwCtr.mu.Unlock() diff --git a/frontend/gateway/gateway.go b/frontend/gateway/gateway.go index eb1fb2a2b05e..9651f93cd7ba 100644 --- a/frontend/gateway/gateway.go +++ b/frontend/gateway/gateway.go @@ -986,11 +986,12 @@ func (lbf *llbBridgeForwarder) Inputs(ctx context.Context, in *pb.InputsRequest) func (lbf *llbBridgeForwarder) NewContainer(ctx context.Context, in *pb.NewContainerRequest) (_ *pb.NewContainerResponse, err error) { bklog.G(ctx).Debugf("|<--- NewContainer %s", in.ContainerID) ctrReq := container.NewContainerRequest{ - ContainerID: in.ContainerID, - NetMode: in.Network, - Hostname: in.Hostname, - Platform: in.Platform, - Constraints: in.Constraints, + ContainerID: in.ContainerID, + NetMode: in.Network, + NetworkConfigID: in.NetworkConfigID, + Hostname: in.Hostname, + Platform: in.Platform, + Constraints: in.Constraints, } for _, m := range in.Mounts { diff --git a/frontend/gateway/grpcclient/client.go b/frontend/gateway/grpcclient/client.go index 524b3ba2a966..94f0c87bb19a 100644 --- a/frontend/gateway/grpcclient/client.go +++ b/frontend/gateway/grpcclient/client.go @@ -769,6 +769,13 @@ func (c *grpcClient) NewContainer(ctx context.Context, req client.NewContainerRe if err != nil { return nil, err } + + if req.NetworkConfigID != "" { + if err := c.caps.Supports(pb.CapGatewayExecNetworkConfig); err != nil { + return nil, err + } + } + id := identity.NewID() var mounts []*opspb.Mount for _, m := range req.Mounts { @@ -794,13 +801,14 @@ func (c *grpcClient) NewContainer(ctx context.Context, req client.NewContainerRe bklog.G(ctx).Debugf("|---> NewContainer %s", id) _, err = c.client.NewContainer(ctx, &pb.NewContainerRequest{ - ContainerID: id, - Mounts: mounts, - Platform: req.Platform, - Constraints: req.Constraints, - Network: req.NetMode, - ExtraHosts: req.ExtraHosts, - Hostname: req.Hostname, + ContainerID: id, + Mounts: mounts, + Platform: req.Platform, + Constraints: req.Constraints, + Network: req.NetMode, + NetworkConfigID: req.NetworkConfigID, + ExtraHosts: req.ExtraHosts, + Hostname: req.Hostname, }) if err != nil { return nil, err diff --git a/frontend/gateway/pb/caps.go b/frontend/gateway/pb/caps.go index 14c6c71ab0f3..f6d92de86c36 100644 --- a/frontend/gateway/pb/caps.go +++ b/frontend/gateway/pb/caps.go @@ -48,6 +48,10 @@ const ( // containers created via gateway exec. CapGatewayExecSecretEnv apicaps.CapID = "gateway.exec.secretenv" + // CapGatewayExecNetworkConfig is the capability to configure network + // settings for containers directly through the gateway + CapGatewayExecNetworkConfig apicaps.CapID = "gateway.exec.networkconfig" + // CapGatewayExecExtraHosts is the capability to send signals to a process // created via gateway exec. CapGatewayExecSignals apicaps.CapID = "gateway.exec.signals" @@ -190,6 +194,13 @@ func init() { Status: apicaps.CapStatusExperimental, }) + Caps.Init(apicaps.Cap{ + ID: CapGatewayExecNetworkConfig, + Name: "gateway exec network config", + Enabled: true, + Status: apicaps.CapStatusExperimental, + }) + Caps.Init(apicaps.Cap{ ID: CapGatewayExecSignals, Name: "gateway exec signals", diff --git a/frontend/gateway/pb/gateway.pb.go b/frontend/gateway/pb/gateway.pb.go index 4849adeea9d3..addf9d74d09c 100644 --- a/frontend/gateway/pb/gateway.pb.go +++ b/frontend/gateway/pb/gateway.pb.go @@ -1840,6 +1840,7 @@ type NewContainerRequest struct { Constraints *pb.WorkerConstraints `protobuf:"bytes,5,opt,name=constraints,proto3" json:"constraints,omitempty"` ExtraHosts []*pb.HostIP `protobuf:"bytes,6,rep,name=extraHosts,proto3" json:"extraHosts,omitempty"` Hostname string `protobuf:"bytes,7,opt,name=hostname,proto3" json:"hostname,omitempty"` + NetworkConfigID string `protobuf:"bytes,8,opt,name=networkConfigID,proto3" json:"networkConfigID,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1927,6 +1928,13 @@ func (m *NewContainerRequest) GetHostname() string { return "" } +func (m *NewContainerRequest) GetNetworkConfigID() string { + if m != nil { + return m.NetworkConfigID + } + return "" +} + type NewContainerResponse struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -2659,164 +2667,165 @@ func init() { func init() { proto.RegisterFile("gateway.proto", fileDescriptor_f1a937782ebbded5) } var fileDescriptor_f1a937782ebbded5 = []byte{ - // 2497 bytes of a gzipped FileDescriptorProto + // 2514 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x59, 0xcf, 0x6f, 0x1b, 0xc7, 0xf5, 0xd7, 0x8a, 0x14, 0x45, 0x3e, 0xfe, 0x10, 0x3d, 0x71, 0xf2, 0xa5, 0x17, 0x81, 0x23, 0xaf, - 0x63, 0x45, 0x96, 0x1d, 0xd2, 0x5f, 0xd9, 0x86, 0x5c, 0xbb, 0x75, 0x62, 0xfd, 0x82, 0x14, 0x4b, + 0x63, 0x45, 0x96, 0x1d, 0xd2, 0x5f, 0xd9, 0x86, 0x5c, 0xbb, 0x75, 0x62, 0xfd, 0x82, 0x18, 0x4b, 0x36, 0x3b, 0x72, 0xe1, 0x22, 0x48, 0x81, 0xae, 0xb8, 0x43, 0x6a, 0xeb, 0xd5, 0xee, 0x76, 0x77, - 0x28, 0x59, 0xc9, 0xa9, 0x87, 0x02, 0x45, 0x8e, 0x3d, 0xf4, 0x96, 0x4b, 0x0b, 0xf4, 0xd4, 0x43, - 0xfb, 0x07, 0x34, 0xe7, 0x00, 0xed, 0xa1, 0xe7, 0x1e, 0x82, 0xc2, 0x7f, 0x44, 0x81, 0xde, 0x8a, - 0x37, 0x33, 0x4b, 0x0e, 0x7f, 0x68, 0x45, 0xd6, 0x27, 0xce, 0xbc, 0x79, 0x3f, 0xe6, 0xbd, 0x37, - 0xef, 0xcd, 0x67, 0x96, 0x50, 0xee, 0xd8, 0x9c, 0x9d, 0xda, 0x67, 0xf5, 0x30, 0x0a, 0x78, 0x40, - 0xae, 0x1c, 0x07, 0x87, 0x67, 0xf5, 0xc3, 0xae, 0xeb, 0x39, 0xaf, 0x5c, 0x5e, 0x3f, 0xf9, 0xff, - 0x7a, 0x3b, 0x0a, 0x7c, 0xce, 0x7c, 0xc7, 0xfc, 0xb8, 0xe3, 0xf2, 0xa3, 0xee, 0x61, 0xbd, 0x15, - 0x1c, 0x37, 0x3a, 0x41, 0x27, 0x68, 0x08, 0x89, 0xc3, 0x6e, 0x5b, 0xcc, 0xc4, 0x44, 0x8c, 0xa4, - 0x26, 0x73, 0x75, 0x98, 0xbd, 0x13, 0x04, 0x1d, 0x8f, 0xd9, 0xa1, 0x1b, 0xab, 0x61, 0x23, 0x0a, - 0x5b, 0x8d, 0x98, 0xdb, 0xbc, 0x1b, 0x2b, 0x99, 0xdb, 0x9a, 0x0c, 0x6e, 0xa4, 0x91, 0x6c, 0xa4, - 0x11, 0x07, 0xde, 0x09, 0x8b, 0x1a, 0xe1, 0x61, 0x23, 0x08, 0x13, 0xee, 0xc6, 0xb9, 0xdc, 0x76, - 0xe8, 0x36, 0xf8, 0x59, 0xc8, 0xe2, 0xc6, 0x69, 0x10, 0xbd, 0x62, 0x91, 0x12, 0xb8, 0x7b, 0xae, - 0x40, 0x97, 0xbb, 0x1e, 0x4a, 0xb5, 0xec, 0x30, 0x46, 0x23, 0xf8, 0xab, 0x84, 0x74, 0xb7, 0x79, - 0xe0, 0xbb, 0x31, 0x77, 0xdd, 0x8e, 0xdb, 0x68, 0xc7, 0x42, 0x46, 0x5a, 0x41, 0x27, 0x14, 0xfb, - 0xfd, 0x14, 0x17, 0xba, 0x51, 0x8b, 0x85, 0x81, 0xe7, 0xb6, 0xce, 0xd0, 0x86, 0x1c, 0x49, 0x31, - 0xeb, 0x6f, 0x59, 0xc8, 0x51, 0x16, 0x77, 0x3d, 0x4e, 0x96, 0xa0, 0x1c, 0xb1, 0xf6, 0x26, 0x0b, - 0x23, 0xd6, 0xb2, 0x39, 0x73, 0x6a, 0xc6, 0xa2, 0xb1, 0x5c, 0xd8, 0x99, 0xa1, 0x83, 0x64, 0xf2, - 0x13, 0xa8, 0x44, 0xac, 0x1d, 0x6b, 0x8c, 0xb3, 0x8b, 0xc6, 0x72, 0x71, 0xf5, 0x56, 0xfd, 0xdc, - 0x1c, 0xd6, 0x29, 0x6b, 0xef, 0xdb, 0x61, 0x5f, 0x64, 0x67, 0x86, 0x0e, 0x29, 0x21, 0xab, 0x90, - 0x89, 0x58, 0xbb, 0x96, 0x11, 0xba, 0xae, 0xa6, 0xeb, 0xda, 0x99, 0xa1, 0xc8, 0x4c, 0xd6, 0x20, - 0x8b, 0x5a, 0x6a, 0x59, 0x21, 0x74, 0xed, 0xc2, 0x0d, 0xec, 0xcc, 0x50, 0x21, 0x40, 0x9e, 0x42, - 0xfe, 0x98, 0x71, 0xdb, 0xb1, 0xb9, 0x5d, 0x83, 0xc5, 0xcc, 0x72, 0x71, 0xb5, 0x91, 0x2a, 0x8c, - 0x01, 0xaa, 0xef, 0x2b, 0x89, 0x2d, 0x9f, 0x47, 0x67, 0xb4, 0xa7, 0x80, 0xbc, 0x84, 0x92, 0xcd, - 0x39, 0xc3, 0x64, 0xb8, 0x81, 0x1f, 0xd7, 0x4a, 0x42, 0xe1, 0xdd, 0x8b, 0x15, 0x3e, 0xd1, 0xa4, - 0xa4, 0xd2, 0x01, 0x45, 0xe6, 0x23, 0x28, 0x0f, 0xd8, 0x24, 0x55, 0xc8, 0xbc, 0x62, 0x67, 0x32, - 0x31, 0x14, 0x87, 0xe4, 0x32, 0xcc, 0x9d, 0xd8, 0x5e, 0x97, 0x89, 0x1c, 0x94, 0xa8, 0x9c, 0x3c, - 0x9c, 0x7d, 0x60, 0x98, 0x47, 0x70, 0x69, 0x44, 0xff, 0x18, 0x05, 0x3f, 0xd2, 0x15, 0x14, 0x57, + 0x28, 0x59, 0xc9, 0xa9, 0x87, 0x02, 0x45, 0x8e, 0x3d, 0xf4, 0x96, 0x4b, 0x0b, 0xf4, 0xdc, 0xfe, + 0x01, 0xcd, 0x39, 0x40, 0x7b, 0xe8, 0xa9, 0x87, 0x1e, 0x82, 0xc2, 0x7f, 0x44, 0x81, 0xde, 0x8a, + 0x37, 0x33, 0x4b, 0x0e, 0x7f, 0x68, 0x45, 0xd5, 0x27, 0xce, 0xbc, 0x79, 0x3f, 0xe6, 0xbd, 0x37, + 0xef, 0xcd, 0x67, 0x96, 0x50, 0xee, 0xda, 0x9c, 0x9d, 0xd8, 0xa7, 0xf5, 0x30, 0x0a, 0x78, 0x40, + 0xae, 0x1c, 0x05, 0x07, 0xa7, 0xf5, 0x83, 0x9e, 0xeb, 0x39, 0xaf, 0x5c, 0x5e, 0x3f, 0xfe, 0xff, + 0x7a, 0x27, 0x0a, 0x7c, 0xce, 0x7c, 0xc7, 0xfc, 0xb8, 0xeb, 0xf2, 0xc3, 0xde, 0x41, 0xbd, 0x1d, + 0x1c, 0x35, 0xba, 0x41, 0x37, 0x68, 0x08, 0x89, 0x83, 0x5e, 0x47, 0xcc, 0xc4, 0x44, 0x8c, 0xa4, + 0x26, 0x73, 0x75, 0x94, 0xbd, 0x1b, 0x04, 0x5d, 0x8f, 0xd9, 0xa1, 0x1b, 0xab, 0x61, 0x23, 0x0a, + 0xdb, 0x8d, 0x98, 0xdb, 0xbc, 0x17, 0x2b, 0x99, 0xdb, 0x9a, 0x0c, 0x6e, 0xa4, 0x91, 0x6c, 0xa4, + 0x11, 0x07, 0xde, 0x31, 0x8b, 0x1a, 0xe1, 0x41, 0x23, 0x08, 0x13, 0xee, 0xc6, 0x99, 0xdc, 0x76, + 0xe8, 0x36, 0xf8, 0x69, 0xc8, 0xe2, 0xc6, 0x49, 0x10, 0xbd, 0x62, 0x91, 0x12, 0xb8, 0x7b, 0xa6, + 0x40, 0x8f, 0xbb, 0x1e, 0x4a, 0xb5, 0xed, 0x30, 0x46, 0x23, 0xf8, 0xab, 0x84, 0x74, 0xb7, 0x79, + 0xe0, 0xbb, 0x31, 0x77, 0xdd, 0xae, 0xdb, 0xe8, 0xc4, 0x42, 0x46, 0x5a, 0x41, 0x27, 0x14, 0xfb, + 0xfd, 0x14, 0x17, 0x7a, 0x51, 0x9b, 0x85, 0x81, 0xe7, 0xb6, 0x4f, 0xd1, 0x86, 0x1c, 0x49, 0x31, + 0xeb, 0xaf, 0x59, 0xc8, 0x51, 0x16, 0xf7, 0x3c, 0x4e, 0x96, 0xa0, 0x1c, 0xb1, 0xce, 0x26, 0x0b, + 0x23, 0xd6, 0xb6, 0x39, 0x73, 0x6a, 0xc6, 0xa2, 0xb1, 0x5c, 0xd8, 0x99, 0xa1, 0xc3, 0x64, 0xf2, + 0x13, 0xa8, 0x44, 0xac, 0x13, 0x6b, 0x8c, 0xb3, 0x8b, 0xc6, 0x72, 0x71, 0xf5, 0x56, 0xfd, 0xcc, + 0x1c, 0xd6, 0x29, 0xeb, 0xec, 0xd9, 0xe1, 0x40, 0x64, 0x67, 0x86, 0x8e, 0x28, 0x21, 0xab, 0x90, + 0x89, 0x58, 0xa7, 0x96, 0x11, 0xba, 0xae, 0xa6, 0xeb, 0xda, 0x99, 0xa1, 0xc8, 0x4c, 0xd6, 0x20, + 0x8b, 0x5a, 0x6a, 0x59, 0x21, 0x74, 0xed, 0xdc, 0x0d, 0xec, 0xcc, 0x50, 0x21, 0x40, 0x9e, 0x42, + 0xfe, 0x88, 0x71, 0xdb, 0xb1, 0xb9, 0x5d, 0x83, 0xc5, 0xcc, 0x72, 0x71, 0xb5, 0x91, 0x2a, 0x8c, + 0x01, 0xaa, 0xef, 0x29, 0x89, 0x2d, 0x9f, 0x47, 0xa7, 0xb4, 0xaf, 0x80, 0xbc, 0x84, 0x92, 0xcd, + 0x39, 0xc3, 0x64, 0xb8, 0x81, 0x1f, 0xd7, 0x4a, 0x42, 0xe1, 0xdd, 0xf3, 0x15, 0x3e, 0xd1, 0xa4, + 0xa4, 0xd2, 0x21, 0x45, 0xe6, 0x23, 0x28, 0x0f, 0xd9, 0x24, 0x55, 0xc8, 0xbc, 0x62, 0xa7, 0x32, + 0x31, 0x14, 0x87, 0xe4, 0x32, 0xcc, 0x1d, 0xdb, 0x5e, 0x8f, 0x89, 0x1c, 0x94, 0xa8, 0x9c, 0x3c, + 0x9c, 0x7d, 0x60, 0x98, 0x87, 0x70, 0x69, 0x4c, 0xff, 0x04, 0x05, 0x3f, 0xd2, 0x15, 0x14, 0x57, 0x3f, 0x4a, 0xd9, 0xb5, 0xae, 0x4e, 0xb3, 0xb4, 0x9e, 0x87, 0x5c, 0x24, 0x1c, 0xb2, 0x7e, 0x67, - 0x40, 0x75, 0x38, 0xd5, 0x64, 0x57, 0x25, 0xc9, 0x10, 0x61, 0xb9, 0x3f, 0xc5, 0x29, 0x41, 0x82, - 0x0a, 0x8c, 0x50, 0x61, 0xae, 0x41, 0xa1, 0x47, 0xba, 0x28, 0x18, 0x05, 0x6d, 0x8b, 0xd6, 0x1a, - 0x64, 0x28, 0x6b, 0x93, 0x0a, 0xcc, 0xba, 0xea, 0x5c, 0xd3, 0x59, 0xd7, 0x21, 0x8b, 0x90, 0x71, - 0x58, 0x5b, 0xb9, 0x5e, 0xa9, 0x87, 0x87, 0xf5, 0x4d, 0xd6, 0x76, 0x7d, 0x17, 0x5d, 0xa4, 0xb8, - 0x64, 0xfd, 0xde, 0xc0, 0xfa, 0xc0, 0x6d, 0x91, 0x4f, 0x06, 0xfc, 0xb8, 0xf8, 0xb4, 0x8f, 0xec, - 0xfe, 0x65, 0xfa, 0xee, 0xef, 0x0d, 0x66, 0xe2, 0x82, 0x12, 0xd0, 0xbd, 0xfb, 0x29, 0x94, 0xf4, - 0xdc, 0x90, 0x1d, 0x28, 0x6a, 0xe7, 0x48, 0x6d, 0x78, 0x69, 0xb2, 0xcc, 0x52, 0x5d, 0xd4, 0xfa, + 0x40, 0x75, 0x34, 0xd5, 0xa4, 0xa9, 0x92, 0x64, 0x88, 0xb0, 0xdc, 0xbf, 0xc0, 0x29, 0x41, 0x82, + 0x0a, 0x8c, 0x50, 0x61, 0xae, 0x41, 0xa1, 0x4f, 0x3a, 0x2f, 0x18, 0x05, 0x6d, 0x8b, 0xd6, 0x1a, + 0x64, 0x28, 0xeb, 0x90, 0x0a, 0xcc, 0xba, 0xea, 0x5c, 0xd3, 0x59, 0xd7, 0x21, 0x8b, 0x90, 0x71, + 0x58, 0x47, 0xb9, 0x5e, 0xa9, 0x87, 0x07, 0xf5, 0x4d, 0xd6, 0x71, 0x7d, 0x17, 0x5d, 0xa4, 0xb8, + 0x64, 0xfd, 0xde, 0xc0, 0xfa, 0xc0, 0x6d, 0x91, 0x4f, 0x86, 0xfc, 0x38, 0xff, 0xb4, 0x8f, 0xed, + 0xfe, 0x65, 0xfa, 0xee, 0xef, 0x0d, 0x67, 0xe2, 0x9c, 0x12, 0xd0, 0xbd, 0xfb, 0x29, 0x94, 0xf4, + 0xdc, 0x90, 0x1d, 0x28, 0x6a, 0xe7, 0x48, 0x6d, 0x78, 0x69, 0xba, 0xcc, 0x52, 0x5d, 0xd4, 0xfa, 0x63, 0x06, 0x8a, 0xda, 0x22, 0x79, 0x0c, 0xd9, 0x57, 0xae, 0x2f, 0x43, 0x58, 0x59, 0x5d, 0x99, - 0x4c, 0xe5, 0x53, 0xd7, 0x77, 0xa8, 0x90, 0x23, 0x4d, 0xad, 0xee, 0x66, 0xc5, 0xb6, 0xee, 0x4d, - 0xa6, 0xe3, 0xdc, 0xe2, 0xbb, 0x33, 0x45, 0xdb, 0x90, 0x4d, 0x83, 0x40, 0x36, 0xb4, 0xf9, 0x91, - 0x68, 0x1a, 0x05, 0x2a, 0xc6, 0xe4, 0x0e, 0xbc, 0xe3, 0xfa, 0x2f, 0x02, 0x1e, 0x34, 0x23, 0xe6, - 0xb8, 0x78, 0xf8, 0x5e, 0x9c, 0x85, 0xac, 0x36, 0x27, 0x58, 0xc6, 0x2d, 0x91, 0x26, 0x54, 0x24, - 0xf9, 0xa0, 0x7b, 0xf8, 0x0b, 0xd6, 0xe2, 0x71, 0x2d, 0x27, 0xfc, 0x59, 0x4e, 0xd9, 0xc2, 0xae, - 0x2e, 0x40, 0x87, 0xe4, 0xdf, 0xaa, 0xda, 0xad, 0xbf, 0x18, 0x50, 0x1e, 0x50, 0x4f, 0x3e, 0x1d, - 0x48, 0xd5, 0xed, 0x49, 0xb7, 0xa5, 0x25, 0xeb, 0x33, 0xc8, 0x39, 0x6e, 0x87, 0xc5, 0x5c, 0xa4, + 0x4e, 0xe5, 0x53, 0xd7, 0x77, 0xa8, 0x90, 0x23, 0x2d, 0xad, 0xee, 0x66, 0xc5, 0xb6, 0xee, 0x4d, + 0xa7, 0xe3, 0xcc, 0xe2, 0xbb, 0x73, 0x81, 0xb6, 0x21, 0x9b, 0x06, 0x81, 0x6c, 0x68, 0xf3, 0x43, + 0xd1, 0x34, 0x0a, 0x54, 0x8c, 0xc9, 0x1d, 0x78, 0xc7, 0xf5, 0x5f, 0x04, 0x3c, 0x68, 0x45, 0xcc, + 0x71, 0xf1, 0xf0, 0xbd, 0x38, 0x0d, 0x59, 0x6d, 0x4e, 0xb0, 0x4c, 0x5a, 0x22, 0x2d, 0xa8, 0x48, + 0xf2, 0x7e, 0xef, 0xe0, 0x17, 0xac, 0xcd, 0xe3, 0x5a, 0x4e, 0xf8, 0xb3, 0x9c, 0xb2, 0x85, 0xa6, + 0x2e, 0x40, 0x47, 0xe4, 0xdf, 0xaa, 0xda, 0xad, 0x3f, 0x1b, 0x50, 0x1e, 0x52, 0x4f, 0x3e, 0x1d, + 0x4a, 0xd5, 0xed, 0x69, 0xb7, 0xa5, 0x25, 0xeb, 0x33, 0xc8, 0x39, 0x6e, 0x97, 0xc5, 0x5c, 0xa4, 0xaa, 0xb0, 0xbe, 0xfa, 0xdd, 0xf7, 0x1f, 0xcc, 0xfc, 0xf3, 0xfb, 0x0f, 0x56, 0xb4, 0xab, 0x26, - 0x08, 0x99, 0xdf, 0x0a, 0x7c, 0x6e, 0xbb, 0x3e, 0x8b, 0xf0, 0x82, 0xfd, 0x58, 0x8a, 0xd4, 0x37, - 0xc5, 0x0f, 0x55, 0x1a, 0x30, 0xe8, 0xbe, 0x7d, 0xcc, 0x44, 0x9e, 0x0a, 0x54, 0x8c, 0x2d, 0x0e, - 0x65, 0xca, 0x78, 0x37, 0xf2, 0x29, 0xfb, 0x65, 0x17, 0x99, 0x7e, 0x90, 0x34, 0x12, 0xb1, 0xe9, - 0x8b, 0x1a, 0x3a, 0x32, 0x52, 0x25, 0x40, 0x96, 0x61, 0x8e, 0x45, 0x51, 0x10, 0xa9, 0xe2, 0x21, - 0x75, 0x79, 0xd5, 0xd7, 0xa3, 0xb0, 0x55, 0x3f, 0x10, 0x57, 0x3d, 0x95, 0x0c, 0x56, 0x15, 0x2a, - 0x89, 0xd5, 0x38, 0x0c, 0xfc, 0x98, 0x59, 0x0b, 0x18, 0xba, 0xb0, 0xcb, 0x63, 0xb5, 0x0f, 0xeb, - 0x5b, 0x03, 0x2a, 0x09, 0x45, 0xf2, 0x90, 0x2f, 0xa0, 0xd8, 0x6f, 0x0d, 0x49, 0x0f, 0x78, 0x98, - 0x1a, 0x54, 0x5d, 0x5e, 0xeb, 0x2b, 0xaa, 0x25, 0xe8, 0xea, 0xcc, 0x67, 0x50, 0x1d, 0x66, 0x18, - 0x93, 0xfd, 0x0f, 0x07, 0x1b, 0xc4, 0x70, 0xbf, 0xd2, 0x4e, 0xc3, 0xb7, 0xb3, 0x70, 0x85, 0x32, - 0x81, 0x5d, 0x76, 0x8f, 0xed, 0x0e, 0xdb, 0x08, 0xfc, 0xb6, 0xdb, 0x49, 0xc2, 0x5c, 0x15, 0xcd, - 0x30, 0xd1, 0x8c, 0x7d, 0x71, 0x19, 0xf2, 0x4d, 0xcf, 0xe6, 0xed, 0x20, 0x3a, 0x56, 0xca, 0x4b, - 0xa8, 0x3c, 0xa1, 0xd1, 0xde, 0x2a, 0x59, 0x84, 0xa2, 0x52, 0xbc, 0x1f, 0x38, 0x49, 0x3a, 0x75, - 0x12, 0xa9, 0xc1, 0xfc, 0x5e, 0xd0, 0x79, 0x86, 0xc9, 0x96, 0x15, 0x96, 0x4c, 0x89, 0x05, 0x25, - 0xc5, 0x18, 0xf5, 0xaa, 0x6b, 0x8e, 0x0e, 0xd0, 0xc8, 0xfb, 0x50, 0x38, 0x60, 0x71, 0xec, 0x06, - 0xfe, 0xee, 0x66, 0x2d, 0x27, 0xe4, 0xfb, 0x04, 0xd4, 0x7d, 0xc0, 0x83, 0x88, 0xed, 0x6e, 0xd6, - 0xe6, 0xa5, 0x6e, 0x35, 0x25, 0xfb, 0x50, 0x39, 0x10, 0x38, 0xa7, 0x89, 0xe8, 0xc6, 0x65, 0x71, - 0x2d, 0x2f, 0x52, 0x74, 0x63, 0x34, 0x45, 0x3a, 0x1e, 0xaa, 0x0b, 0xf6, 0x33, 0x3a, 0x24, 0x6c, - 0xfd, 0xd6, 0x00, 0x73, 0x5c, 0x00, 0xd5, 0x69, 0xf8, 0x0c, 0x72, 0xf2, 0x7c, 0xcb, 0x20, 0xfe, - 0x6f, 0x95, 0x21, 0x7f, 0xc9, 0x7b, 0x90, 0x93, 0xda, 0x55, 0x51, 0xab, 0x59, 0x92, 0xa5, 0x4c, - 0x2f, 0x4b, 0xd6, 0xaf, 0x73, 0x50, 0x3a, 0xc0, 0x2d, 0x25, 0x89, 0xac, 0x03, 0xf4, 0xf3, 0xaf, - 0x6a, 0x66, 0xf8, 0x54, 0x68, 0x1c, 0xc4, 0x84, 0xfc, 0xb6, 0x3a, 0x9f, 0xea, 0x8a, 0xec, 0xcd, - 0xc9, 0xe7, 0x50, 0x4c, 0xc6, 0xcf, 0x43, 0x5e, 0xcb, 0x88, 0xe8, 0x3d, 0x48, 0x39, 0xe0, 0xfa, - 0x4e, 0xea, 0x9a, 0xa8, 0x3a, 0xde, 0x1a, 0x85, 0xdc, 0x86, 0x4b, 0xb6, 0xe7, 0x05, 0xa7, 0xaa, - 0x66, 0x45, 0xf5, 0x89, 0xec, 0xe7, 0xe9, 0xe8, 0x02, 0xf6, 0x62, 0x8d, 0xf8, 0x24, 0x8a, 0xec, - 0x33, 0x0c, 0x44, 0x4e, 0xf0, 0x8f, 0x5b, 0xc2, 0xb6, 0xb8, 0xed, 0xfa, 0xb6, 0x57, 0x03, 0xc1, - 0x23, 0x27, 0x78, 0xdc, 0xb6, 0x5e, 0x87, 0x41, 0xc4, 0x59, 0xf4, 0x84, 0xf3, 0xa8, 0x56, 0x14, - 0xe1, 0x1d, 0xa0, 0x91, 0x26, 0x94, 0x36, 0xec, 0xd6, 0x11, 0xdb, 0x3d, 0x46, 0x62, 0x02, 0xdd, - 0xd2, 0x9a, 0xa5, 0x60, 0x7f, 0x1e, 0xea, 0x98, 0x4d, 0xd7, 0x40, 0x5a, 0x50, 0x49, 0x5c, 0x97, - 0x2d, 0xa0, 0x56, 0x16, 0x3a, 0x1f, 0x4d, 0x1b, 0x4a, 0x29, 0x2d, 0x4d, 0x0c, 0xa9, 0xc4, 0x44, - 0x6e, 0x61, 0xb5, 0xdb, 0x9c, 0xd5, 0x2a, 0xc2, 0xe7, 0xde, 0x7c, 0x4c, 0x25, 0x2c, 0xbc, 0x45, - 0x25, 0x98, 0x8f, 0xa1, 0x3a, 0x9c, 0xdc, 0x69, 0x90, 0x97, 0xf9, 0x63, 0x78, 0x67, 0x8c, 0x47, - 0x6f, 0xd5, 0xdd, 0xfe, 0x6c, 0xc0, 0xa5, 0x91, 0x34, 0xe0, 0x0d, 0x23, 0xba, 0x8a, 0x54, 0x29, - 0xc6, 0x64, 0x1f, 0xe6, 0x30, 0xcd, 0xb1, 0xc2, 0x1a, 0x6b, 0xd3, 0xe4, 0xb5, 0x2e, 0x24, 0x65, - 0xfc, 0xa5, 0x16, 0xf3, 0x01, 0x40, 0x9f, 0x38, 0x15, 0xfe, 0xfc, 0x02, 0xca, 0x2a, 0xc9, 0xaa, - 0x83, 0x54, 0x25, 0x6c, 0x51, 0xc2, 0x08, 0x4b, 0xfa, 0x97, 0x5f, 0x66, 0xca, 0xcb, 0xcf, 0xfa, - 0x0a, 0x16, 0x28, 0xb3, 0x9d, 0x6d, 0xd7, 0x63, 0xe7, 0xf7, 0x78, 0x2c, 0x7e, 0xd7, 0x63, 0x4d, - 0x84, 0x3e, 0x49, 0xf1, 0xab, 0x39, 0x79, 0x08, 0x73, 0xd4, 0xf6, 0x3b, 0x4c, 0x99, 0xfe, 0x30, - 0xc5, 0xb4, 0x30, 0x82, 0xbc, 0x54, 0x8a, 0x58, 0x8f, 0xa0, 0xd0, 0xa3, 0x61, 0x33, 0x7b, 0xde, - 0x6e, 0xc7, 0x4c, 0x36, 0xc6, 0x0c, 0x55, 0x33, 0xa4, 0xef, 0x31, 0xbf, 0xa3, 0x4c, 0x67, 0xa8, - 0x9a, 0x59, 0x4b, 0xf8, 0x5e, 0x48, 0x76, 0xae, 0x42, 0x43, 0x20, 0xbb, 0x89, 0xf8, 0xd0, 0x10, - 0xf5, 0x2a, 0xc6, 0x96, 0x83, 0x97, 0xb6, 0xed, 0x6c, 0xba, 0xd1, 0xf9, 0x0e, 0xd6, 0x60, 0x7e, - 0xd3, 0x8d, 0x34, 0xff, 0x92, 0x29, 0x59, 0xc2, 0xeb, 0xbc, 0xe5, 0x75, 0x1d, 0xf4, 0x96, 0xb3, - 0xc8, 0x57, 0x5d, 0x75, 0x88, 0x6a, 0x7d, 0x22, 0xe3, 0x28, 0xac, 0xa8, 0xcd, 0xdc, 0x86, 0x79, - 0xe6, 0xf3, 0x08, 0xcb, 0x48, 0xde, 0xf9, 0xa4, 0x2e, 0x5f, 0xe0, 0x75, 0xf1, 0x02, 0x17, 0xd8, - 0x82, 0x26, 0x2c, 0xd6, 0x1a, 0x2c, 0x20, 0x21, 0x3d, 0x11, 0x04, 0xb2, 0xda, 0x26, 0xc5, 0xd8, - 0x7a, 0x08, 0xd5, 0xbe, 0xa0, 0x32, 0xbd, 0x04, 0x59, 0x04, 0xbf, 0xaa, 0xaf, 0x8f, 0xb3, 0x2b, - 0xd6, 0xad, 0xeb, 0xb0, 0x90, 0x14, 0xff, 0xb9, 0x46, 0x2d, 0x02, 0xd5, 0x3e, 0x93, 0xc2, 0x3d, - 0x65, 0x28, 0x36, 0x5d, 0x3f, 0x81, 0x05, 0xd6, 0x1b, 0x03, 0x4a, 0xcd, 0xc0, 0xef, 0xdf, 0x72, - 0x4d, 0x58, 0x48, 0x4a, 0xf7, 0x49, 0x73, 0x77, 0xc3, 0x0e, 0x93, 0x18, 0x2c, 0x8e, 0x9e, 0x0f, - 0xf5, 0x0d, 0xa3, 0x2e, 0x19, 0xd7, 0xb3, 0x78, 0x21, 0xd2, 0x61, 0x71, 0xf2, 0x29, 0xcc, 0xef, - 0xed, 0xad, 0x0b, 0x4d, 0xb3, 0x53, 0x69, 0x4a, 0xc4, 0xc8, 0x63, 0x98, 0x7f, 0x29, 0x3e, 0xad, - 0xc4, 0xea, 0x8a, 0x1a, 0x73, 0x56, 0x65, 0x84, 0x24, 0x1b, 0x65, 0xad, 0x20, 0x72, 0x68, 0x22, - 0x64, 0xfd, 0xdb, 0x80, 0xe2, 0x4b, 0xbb, 0x0f, 0x39, 0xfb, 0x18, 0xf7, 0x2d, 0x6e, 0x72, 0x85, - 0x71, 0x2f, 0xc3, 0x9c, 0xc7, 0x4e, 0x98, 0xa7, 0xce, 0xb8, 0x9c, 0x20, 0x35, 0x3e, 0x0a, 0x22, - 0x59, 0xd6, 0x25, 0x2a, 0x27, 0x58, 0x10, 0x0e, 0xe3, 0xb6, 0xeb, 0xd5, 0xb2, 0x8b, 0x19, 0xbc, - 0xf5, 0xe5, 0x0c, 0x33, 0xd7, 0x8d, 0x3c, 0xf5, 0xf0, 0xc0, 0x21, 0xb1, 0x20, 0xeb, 0xfa, 0xed, - 0x40, 0xdc, 0x7f, 0xaa, 0x2d, 0xca, 0x16, 0xbd, 0xeb, 0xb7, 0x03, 0x2a, 0xd6, 0xc8, 0x35, 0xc8, + 0x08, 0x99, 0xdf, 0x0e, 0x7c, 0x6e, 0xbb, 0x3e, 0x8b, 0xf0, 0x82, 0xfd, 0x58, 0x8a, 0xd4, 0x37, + 0xc5, 0x0f, 0x55, 0x1a, 0x30, 0xe8, 0xbe, 0x7d, 0xc4, 0x44, 0x9e, 0x0a, 0x54, 0x8c, 0x2d, 0x0e, + 0x65, 0xca, 0x78, 0x2f, 0xf2, 0x29, 0xfb, 0x65, 0x0f, 0x99, 0x7e, 0x90, 0x34, 0x12, 0xb1, 0xe9, + 0xf3, 0x1a, 0x3a, 0x32, 0x52, 0x25, 0x40, 0x96, 0x61, 0x8e, 0x45, 0x51, 0x10, 0xa9, 0xe2, 0x21, + 0x75, 0x79, 0xd5, 0xd7, 0xa3, 0xb0, 0x5d, 0xdf, 0x17, 0x57, 0x3d, 0x95, 0x0c, 0x56, 0x15, 0x2a, + 0x89, 0xd5, 0x38, 0x0c, 0xfc, 0x98, 0x59, 0x0b, 0x18, 0xba, 0xb0, 0xc7, 0x63, 0xb5, 0x0f, 0xeb, + 0x5b, 0x03, 0x2a, 0x09, 0x45, 0xf2, 0x90, 0x2f, 0xa0, 0x38, 0x68, 0x0d, 0x49, 0x0f, 0x78, 0x98, + 0x1a, 0x54, 0x5d, 0x5e, 0xeb, 0x2b, 0xaa, 0x25, 0xe8, 0xea, 0xcc, 0x67, 0x50, 0x1d, 0x65, 0x98, + 0x90, 0xfd, 0x0f, 0x87, 0x1b, 0xc4, 0x68, 0xbf, 0xd2, 0x4e, 0xc3, 0xb7, 0xb3, 0x70, 0x85, 0x32, + 0x81, 0x5d, 0x9a, 0x47, 0x76, 0x97, 0x6d, 0x04, 0x7e, 0xc7, 0xed, 0x26, 0x61, 0xae, 0x8a, 0x66, + 0x98, 0x68, 0xc6, 0xbe, 0xb8, 0x0c, 0xf9, 0x96, 0x67, 0xf3, 0x4e, 0x10, 0x1d, 0x29, 0xe5, 0x25, + 0x54, 0x9e, 0xd0, 0x68, 0x7f, 0x95, 0x2c, 0x42, 0x51, 0x29, 0xde, 0x0b, 0x9c, 0x24, 0x9d, 0x3a, + 0x89, 0xd4, 0x60, 0x7e, 0x37, 0xe8, 0x3e, 0xc3, 0x64, 0xcb, 0x0a, 0x4b, 0xa6, 0xc4, 0x82, 0x92, + 0x62, 0x8c, 0xfa, 0xd5, 0x35, 0x47, 0x87, 0x68, 0xe4, 0x7d, 0x28, 0xec, 0xb3, 0x38, 0x76, 0x03, + 0xbf, 0xb9, 0x59, 0xcb, 0x09, 0xf9, 0x01, 0x01, 0x75, 0xef, 0xf3, 0x20, 0x62, 0xcd, 0xcd, 0xda, + 0xbc, 0xd4, 0xad, 0xa6, 0x64, 0x0f, 0x2a, 0xfb, 0x02, 0xe7, 0xb4, 0x10, 0xdd, 0xb8, 0x2c, 0xae, + 0xe5, 0x45, 0x8a, 0x6e, 0x8c, 0xa7, 0x48, 0xc7, 0x43, 0x75, 0xc1, 0x7e, 0x4a, 0x47, 0x84, 0xad, + 0xdf, 0x1a, 0x60, 0x4e, 0x0a, 0xa0, 0x3a, 0x0d, 0x9f, 0x41, 0x4e, 0x9e, 0x6f, 0x19, 0xc4, 0xff, + 0xad, 0x32, 0xe4, 0x2f, 0x79, 0x0f, 0x72, 0x52, 0xbb, 0x2a, 0x6a, 0x35, 0x4b, 0xb2, 0x94, 0xe9, + 0x67, 0xc9, 0xfa, 0x75, 0x0e, 0x4a, 0xfb, 0xb8, 0xa5, 0x24, 0x91, 0x75, 0x80, 0x41, 0xfe, 0x55, + 0xcd, 0x8c, 0x9e, 0x0a, 0x8d, 0x83, 0x98, 0x90, 0xdf, 0x56, 0xe7, 0x53, 0x5d, 0x91, 0xfd, 0x39, + 0xf9, 0x1c, 0x8a, 0xc9, 0xf8, 0x79, 0xc8, 0x6b, 0x19, 0x11, 0xbd, 0x07, 0x29, 0x07, 0x5c, 0xdf, + 0x49, 0x5d, 0x13, 0x55, 0xc7, 0x5b, 0xa3, 0x90, 0xdb, 0x70, 0xc9, 0xf6, 0xbc, 0xe0, 0x44, 0xd5, + 0xac, 0xa8, 0x3e, 0x91, 0xfd, 0x3c, 0x1d, 0x5f, 0xc0, 0x5e, 0xac, 0x11, 0x9f, 0x44, 0x91, 0x7d, + 0x8a, 0x81, 0xc8, 0x09, 0xfe, 0x49, 0x4b, 0xd8, 0x16, 0xb7, 0x5d, 0xdf, 0xf6, 0x6a, 0x20, 0x78, + 0xe4, 0x04, 0x8f, 0xdb, 0xd6, 0xeb, 0x30, 0x88, 0x38, 0x8b, 0x9e, 0x70, 0x1e, 0xd5, 0x8a, 0x22, + 0xbc, 0x43, 0x34, 0xd2, 0x82, 0xd2, 0x86, 0xdd, 0x3e, 0x64, 0xcd, 0x23, 0x24, 0x26, 0xd0, 0x2d, + 0xad, 0x59, 0x0a, 0xf6, 0xe7, 0xa1, 0x8e, 0xd9, 0x74, 0x0d, 0xa4, 0x0d, 0x95, 0xc4, 0x75, 0xd9, + 0x02, 0x6a, 0x65, 0xa1, 0xf3, 0xd1, 0x45, 0x43, 0x29, 0xa5, 0xa5, 0x89, 0x11, 0x95, 0x98, 0xc8, + 0x2d, 0xac, 0x76, 0x9b, 0xb3, 0x5a, 0x45, 0xf8, 0xdc, 0x9f, 0x4f, 0xa8, 0x84, 0x85, 0xb7, 0xa8, + 0x04, 0xf3, 0x31, 0x54, 0x47, 0x93, 0x7b, 0x11, 0xe4, 0x65, 0xfe, 0x18, 0xde, 0x99, 0xe0, 0xd1, + 0x5b, 0x75, 0xb7, 0x3f, 0x19, 0x70, 0x69, 0x2c, 0x0d, 0x78, 0xc3, 0x88, 0xae, 0x22, 0x55, 0x8a, + 0x31, 0xd9, 0x83, 0x39, 0x4c, 0x73, 0xac, 0xb0, 0xc6, 0xda, 0x45, 0xf2, 0x5a, 0x17, 0x92, 0x32, + 0xfe, 0x52, 0x8b, 0xf9, 0x00, 0x60, 0x40, 0xbc, 0x10, 0xfe, 0xfc, 0x02, 0xca, 0x2a, 0xc9, 0xaa, + 0x83, 0x54, 0x25, 0x6c, 0x51, 0xc2, 0x08, 0x4b, 0x06, 0x97, 0x5f, 0xe6, 0x82, 0x97, 0x9f, 0xf5, + 0x15, 0x2c, 0x50, 0x66, 0x3b, 0xdb, 0xae, 0xc7, 0xce, 0xee, 0xf1, 0x58, 0xfc, 0xae, 0xc7, 0x5a, + 0x08, 0x7d, 0x92, 0xe2, 0x57, 0x73, 0xf2, 0x10, 0xe6, 0xa8, 0xed, 0x77, 0x99, 0x32, 0xfd, 0x61, + 0x8a, 0x69, 0x61, 0x04, 0x79, 0xa9, 0x14, 0xb1, 0x1e, 0x41, 0xa1, 0x4f, 0xc3, 0x66, 0xf6, 0xbc, + 0xd3, 0x89, 0x99, 0x6c, 0x8c, 0x19, 0xaa, 0x66, 0x48, 0xdf, 0x65, 0x7e, 0x57, 0x99, 0xce, 0x50, + 0x35, 0xb3, 0x96, 0xf0, 0xbd, 0x90, 0xec, 0x5c, 0x85, 0x86, 0x40, 0x76, 0x13, 0xf1, 0xa1, 0x21, + 0xea, 0x55, 0x8c, 0x2d, 0x07, 0x2f, 0x6d, 0xdb, 0xd9, 0x74, 0xa3, 0xb3, 0x1d, 0xac, 0xc1, 0xfc, + 0xa6, 0x1b, 0x69, 0xfe, 0x25, 0x53, 0xb2, 0x84, 0xd7, 0x79, 0xdb, 0xeb, 0x39, 0xe8, 0x2d, 0x67, + 0x91, 0xaf, 0xba, 0xea, 0x08, 0xd5, 0xfa, 0x44, 0xc6, 0x51, 0x58, 0x51, 0x9b, 0xb9, 0x0d, 0xf3, + 0xcc, 0xe7, 0x11, 0x96, 0x91, 0xbc, 0xf3, 0x49, 0x5d, 0xbe, 0xc0, 0xeb, 0xe2, 0x05, 0x2e, 0xb0, + 0x05, 0x4d, 0x58, 0xac, 0x35, 0x58, 0x40, 0x42, 0x7a, 0x22, 0x08, 0x64, 0xb5, 0x4d, 0x8a, 0xb1, + 0xf5, 0x10, 0xaa, 0x03, 0x41, 0x65, 0x7a, 0x09, 0xb2, 0x08, 0x7e, 0x55, 0x5f, 0x9f, 0x64, 0x57, + 0xac, 0x5b, 0xd7, 0x61, 0x21, 0x29, 0xfe, 0x33, 0x8d, 0x5a, 0x04, 0xaa, 0x03, 0x26, 0x85, 0x7b, + 0xca, 0x50, 0x6c, 0xb9, 0x7e, 0x02, 0x0b, 0xac, 0x37, 0x06, 0x94, 0x5a, 0x81, 0x3f, 0xb8, 0xe5, + 0x5a, 0xb0, 0x90, 0x94, 0xee, 0x93, 0x56, 0x73, 0xc3, 0x0e, 0x93, 0x18, 0x2c, 0x8e, 0x9f, 0x0f, + 0xf5, 0x0d, 0xa3, 0x2e, 0x19, 0xd7, 0xb3, 0x78, 0x21, 0xd2, 0x51, 0x71, 0xf2, 0x29, 0xcc, 0xef, + 0xee, 0xae, 0x0b, 0x4d, 0xb3, 0x17, 0xd2, 0x94, 0x88, 0x91, 0xc7, 0x30, 0xff, 0x52, 0x7c, 0x5a, + 0x89, 0xd5, 0x15, 0x35, 0xe1, 0xac, 0xca, 0x08, 0x49, 0x36, 0xca, 0xda, 0x41, 0xe4, 0xd0, 0x44, + 0xc8, 0xfa, 0xb7, 0x01, 0xc5, 0x97, 0xf6, 0x00, 0x72, 0x0e, 0x30, 0xee, 0x5b, 0xdc, 0xe4, 0x0a, + 0xe3, 0x5e, 0x86, 0x39, 0x8f, 0x1d, 0x33, 0x4f, 0x9d, 0x71, 0x39, 0x41, 0x6a, 0x7c, 0x18, 0x44, + 0xb2, 0xac, 0x4b, 0x54, 0x4e, 0xb0, 0x20, 0x1c, 0xc6, 0x6d, 0xd7, 0xab, 0x65, 0x17, 0x33, 0x78, + 0xeb, 0xcb, 0x19, 0x66, 0xae, 0x17, 0x79, 0xea, 0xe1, 0x81, 0x43, 0x62, 0x41, 0xd6, 0xf5, 0x3b, + 0x81, 0xb8, 0xff, 0x54, 0x5b, 0x94, 0x2d, 0xba, 0xe9, 0x77, 0x02, 0x2a, 0xd6, 0xc8, 0x35, 0xc8, 0x45, 0x58, 0x7f, 0x71, 0x6d, 0x5e, 0x04, 0xa5, 0x80, 0x5c, 0xb2, 0x4a, 0xd5, 0x82, 0x55, 0x81, - 0x92, 0xf4, 0x5b, 0x25, 0xff, 0x4f, 0xb3, 0xf0, 0xce, 0x33, 0x76, 0xba, 0x91, 0xf8, 0x95, 0x04, - 0x64, 0x11, 0x8a, 0x3d, 0xda, 0xee, 0xa6, 0x3a, 0x42, 0x3a, 0x09, 0x8d, 0xed, 0x07, 0x5d, 0x9f, - 0x27, 0x39, 0x14, 0xc6, 0x04, 0x85, 0xaa, 0x05, 0x72, 0x03, 0xe6, 0x9f, 0x31, 0x7e, 0x1a, 0x44, - 0xaf, 0x84, 0xd7, 0x95, 0xd5, 0x22, 0xf2, 0x3c, 0x63, 0x1c, 0x11, 0x22, 0x4d, 0xd6, 0x10, 0x76, - 0x86, 0x09, 0xec, 0xcc, 0x8e, 0x83, 0x9d, 0xc9, 0x2a, 0x59, 0x83, 0x62, 0x2b, 0xf0, 0x63, 0x1e, - 0xd9, 0x2e, 0x1a, 0x9e, 0x13, 0xcc, 0xef, 0x22, 0xb3, 0x4c, 0xec, 0x46, 0x7f, 0x91, 0xea, 0x9c, - 0x64, 0x05, 0x80, 0xbd, 0xe6, 0x91, 0xbd, 0x13, 0xc4, 0xbd, 0x27, 0x1a, 0xa0, 0x1c, 0x12, 0x76, - 0x9b, 0x54, 0x5b, 0xc5, 0x0e, 0x79, 0x14, 0xc4, 0x5c, 0xbc, 0x53, 0x24, 0xbc, 0xec, 0xcd, 0xad, - 0xf7, 0xe0, 0xf2, 0x60, 0xb4, 0x54, 0x18, 0x1f, 0xc1, 0xff, 0x51, 0xe6, 0x31, 0x3b, 0x66, 0xd3, - 0x47, 0xd2, 0x32, 0xa1, 0x36, 0x2a, 0xac, 0x14, 0xff, 0x27, 0x03, 0xc5, 0xad, 0xd7, 0xac, 0xb5, - 0xcf, 0xe2, 0xd8, 0xee, 0x08, 0x60, 0xdc, 0x8c, 0x82, 0x16, 0x8b, 0xe3, 0x9e, 0xae, 0x3e, 0x81, - 0xfc, 0x10, 0xb2, 0xbb, 0xbe, 0xcb, 0xd5, 0xdd, 0xb9, 0x94, 0xfa, 0x2e, 0x71, 0xb9, 0xd2, 0xb9, - 0x33, 0x43, 0x85, 0x14, 0x79, 0x08, 0x59, 0xec, 0x3c, 0x93, 0x74, 0x7f, 0x47, 0x93, 0x45, 0x19, - 0xb2, 0x2e, 0xbe, 0x1f, 0xba, 0x5f, 0x32, 0x95, 0xc1, 0xe5, 0xf4, 0x6b, 0xcb, 0xfd, 0x92, 0xf5, - 0x35, 0x28, 0x49, 0xb2, 0x85, 0xb0, 0xde, 0x8e, 0x38, 0x73, 0x54, 0x66, 0x6f, 0xa6, 0x81, 0x25, - 0xc9, 0xd9, 0xd7, 0x92, 0xc8, 0x62, 0x10, 0xb6, 0x5e, 0xbb, 0x5c, 0x55, 0x4a, 0x5a, 0x10, 0x90, - 0x4d, 0x73, 0x04, 0xa7, 0x28, 0xbd, 0x19, 0xf8, 0x32, 0xf3, 0xe9, 0xd2, 0xc8, 0xa6, 0x49, 0xe3, - 0x14, 0xc3, 0x70, 0xe0, 0x76, 0x10, 0x83, 0xe6, 0x2f, 0x0c, 0x83, 0x64, 0xd4, 0xc2, 0x20, 0x09, - 0xeb, 0xf3, 0x30, 0x27, 0x20, 0x92, 0xf5, 0x77, 0x03, 0x8a, 0x5a, 0x9e, 0x26, 0xa8, 0xc9, 0xf7, - 0x21, 0xbb, 0xcf, 0xc4, 0x37, 0x15, 0x34, 0x9e, 0x17, 0x15, 0xc9, 0xb8, 0x4d, 0x05, 0x15, 0x9b, - 0xca, 0xb6, 0x23, 0x1b, 0x66, 0x99, 0xe2, 0x10, 0x29, 0x2f, 0xf8, 0x99, 0x48, 0x59, 0x9e, 0xe2, - 0x90, 0xdc, 0x86, 0xfc, 0x01, 0x6b, 0x75, 0x23, 0x97, 0x9f, 0x89, 0x24, 0x54, 0x56, 0xab, 0xa2, - 0xd5, 0x28, 0x9a, 0x28, 0xdc, 0x1e, 0x07, 0xb9, 0x05, 0x85, 0x98, 0xb5, 0x22, 0xc6, 0x99, 0x7f, - 0xa2, 0xaa, 0xaa, 0xac, 0xd8, 0x23, 0xc6, 0xb7, 0xfc, 0x13, 0xda, 0x5f, 0xb7, 0x9e, 0xe2, 0x49, - 0xee, 0x7b, 0x43, 0x20, 0xbb, 0x81, 0x6f, 0x47, 0x74, 0xa3, 0x4c, 0xc5, 0x18, 0x9f, 0xef, 0x5b, - 0x17, 0x3d, 0xdf, 0xb7, 0x92, 0xe7, 0xfb, 0xe0, 0x09, 0xc0, 0x6b, 0x4c, 0xcb, 0x88, 0xf5, 0x04, - 0x0a, 0xbd, 0x53, 0x4a, 0x2a, 0x30, 0xbb, 0xed, 0x28, 0x4b, 0xb3, 0xdb, 0x0e, 0xfa, 0xbd, 0xf5, - 0x7c, 0x5b, 0x58, 0xc9, 0x53, 0x1c, 0xf6, 0xd0, 0x46, 0x46, 0x43, 0x1b, 0x6b, 0x50, 0x1e, 0x38, - 0xaa, 0xc8, 0x44, 0x83, 0xd3, 0x38, 0xd9, 0x32, 0x8e, 0xa5, 0x1b, 0x5e, 0x2c, 0x74, 0x09, 0x37, - 0xbc, 0xd8, 0xba, 0x0e, 0xe5, 0x81, 0xe4, 0x22, 0x93, 0x78, 0x09, 0x2b, 0x50, 0x8a, 0xe3, 0x15, - 0x06, 0x0b, 0x43, 0x1f, 0xc7, 0xc8, 0x0d, 0xc8, 0xc9, 0x8f, 0x30, 0xd5, 0x19, 0xf3, 0xca, 0xd7, - 0xdf, 0x2c, 0xbe, 0x3b, 0xc4, 0x20, 0x17, 0x91, 0x6d, 0xbd, 0xeb, 0x3b, 0x1e, 0xab, 0x1a, 0x63, - 0xd9, 0xe4, 0xa2, 0x99, 0xfd, 0xcd, 0x1f, 0xae, 0xce, 0xac, 0xd8, 0x70, 0x69, 0xe4, 0xc3, 0x0e, - 0xb9, 0x0e, 0xd9, 0x03, 0xe6, 0xb5, 0x13, 0x33, 0x23, 0x0c, 0xb8, 0x48, 0xae, 0x41, 0x86, 0xda, - 0xa7, 0x55, 0xc3, 0xac, 0x7d, 0xfd, 0xcd, 0xe2, 0xe5, 0xd1, 0xaf, 0x43, 0xf6, 0xa9, 0x34, 0xb1, - 0xfa, 0x57, 0x80, 0xc2, 0xde, 0xde, 0xfa, 0x7a, 0xe4, 0x3a, 0x1d, 0x46, 0x7e, 0x65, 0x00, 0x19, - 0x7d, 0x33, 0x93, 0x7b, 0xe9, 0x0d, 0x61, 0xfc, 0x37, 0x0a, 0xf3, 0xfe, 0x94, 0x52, 0x0a, 0xb2, - 0x7c, 0x0e, 0x73, 0x02, 0x67, 0x93, 0x8f, 0x26, 0x7c, 0x6e, 0x99, 0xcb, 0x17, 0x33, 0x2a, 0xdd, - 0x2d, 0xc8, 0x27, 0x58, 0x95, 0xac, 0xa4, 0x6e, 0x6f, 0x00, 0x8a, 0x9b, 0xb7, 0x26, 0xe2, 0x55, - 0x46, 0x7e, 0x0e, 0xf3, 0x0a, 0x82, 0x92, 0x9b, 0x17, 0xc8, 0xf5, 0xc1, 0xb0, 0xb9, 0x32, 0x09, - 0x6b, 0xdf, 0x8d, 0x04, 0x6a, 0xa6, 0xba, 0x31, 0x04, 0x64, 0x53, 0xdd, 0x18, 0xc1, 0xae, 0xad, - 0xfe, 0x03, 0x35, 0xd5, 0xc8, 0x10, 0x70, 0x4d, 0x35, 0x32, 0x8c, 0x5f, 0xc9, 0x4b, 0xc8, 0x22, - 0x7e, 0x25, 0x69, 0xbd, 0x5a, 0x03, 0xb8, 0x66, 0xda, 0x99, 0x18, 0x00, 0xbe, 0x3f, 0xc3, 0x3b, - 0x4d, 0x7c, 0x8b, 0x48, 0xbf, 0xcd, 0xb4, 0x6f, 0x97, 0xe6, 0xcd, 0x09, 0x38, 0xfb, 0xea, 0xd5, - 0x3b, 0x7e, 0x79, 0x82, 0x0f, 0x88, 0x17, 0xab, 0x1f, 0xfa, 0x54, 0x19, 0x40, 0x49, 0x87, 0x2a, - 0xa4, 0x9e, 0x22, 0x3a, 0x06, 0x01, 0x9a, 0x8d, 0x89, 0xf9, 0x95, 0xc1, 0xaf, 0xf0, 0x11, 0x37, - 0x08, 0x63, 0xc8, 0x6a, 0x6a, 0x38, 0xc6, 0x02, 0x26, 0xf3, 0xee, 0x54, 0x32, 0xca, 0xb8, 0x2d, - 0x61, 0x92, 0x82, 0x42, 0x24, 0xfd, 0xd6, 0xef, 0xc1, 0x29, 0x73, 0x42, 0xbe, 0x65, 0xe3, 0x8e, - 0x81, 0xe7, 0x0c, 0xa1, 0x73, 0xaa, 0x6e, 0xed, 0x4d, 0x91, 0x7a, 0xce, 0x74, 0x0c, 0xbe, 0x5e, - 0xfa, 0xee, 0xcd, 0x55, 0xe3, 0x1f, 0x6f, 0xae, 0x1a, 0xff, 0x7a, 0x73, 0xd5, 0x38, 0xcc, 0x89, - 0x7f, 0x64, 0xef, 0xfe, 0x37, 0x00, 0x00, 0xff, 0xff, 0x20, 0x47, 0x7d, 0x27, 0x1a, 0x1f, 0x00, - 0x00, + 0x92, 0xf4, 0x5b, 0x25, 0xff, 0x1f, 0xb3, 0xf0, 0xce, 0x33, 0x76, 0xb2, 0x91, 0xf8, 0x95, 0x04, + 0x64, 0x11, 0x8a, 0x7d, 0x5a, 0x73, 0x53, 0x1d, 0x21, 0x9d, 0x84, 0xc6, 0xf6, 0x82, 0x9e, 0xcf, + 0x93, 0x1c, 0x0a, 0x63, 0x82, 0x42, 0xd5, 0x02, 0xb9, 0x01, 0xf3, 0xcf, 0x18, 0x3f, 0x09, 0xa2, + 0x57, 0xc2, 0xeb, 0xca, 0x6a, 0x11, 0x79, 0x9e, 0x31, 0x8e, 0x08, 0x91, 0x26, 0x6b, 0x08, 0x3b, + 0xc3, 0x04, 0x76, 0x66, 0x27, 0xc1, 0xce, 0x64, 0x95, 0xac, 0x41, 0xb1, 0x1d, 0xf8, 0x31, 0x8f, + 0x6c, 0x17, 0x0d, 0xcf, 0x09, 0xe6, 0x77, 0x91, 0x59, 0x26, 0x76, 0x63, 0xb0, 0x48, 0x75, 0x4e, + 0xb2, 0x02, 0xc0, 0x5e, 0xf3, 0xc8, 0xde, 0x09, 0xe2, 0xfe, 0x13, 0x0d, 0x50, 0x0e, 0x09, 0xcd, + 0x16, 0xd5, 0x56, 0xb1, 0x43, 0x1e, 0x06, 0x31, 0x17, 0xef, 0x14, 0x09, 0x2f, 0xfb, 0x73, 0xb2, + 0x0c, 0x0b, 0xbe, 0xdc, 0xb5, 0x84, 0x67, 0xcd, 0xcd, 0x5a, 0x5e, 0xb0, 0x8c, 0x92, 0xad, 0xf7, + 0xe0, 0xf2, 0x70, 0x5c, 0x55, 0xc0, 0x1f, 0xc1, 0xff, 0x51, 0xe6, 0x31, 0x3b, 0x66, 0x17, 0x8f, + 0xb9, 0x65, 0x42, 0x6d, 0x5c, 0x58, 0x29, 0xfe, 0x4f, 0x06, 0x8a, 0x5b, 0xaf, 0x59, 0x7b, 0x8f, + 0xc5, 0xb1, 0xdd, 0x15, 0x10, 0xba, 0x15, 0x05, 0x6d, 0x16, 0xc7, 0x7d, 0x5d, 0x03, 0x02, 0xf9, + 0x21, 0x64, 0x9b, 0xbe, 0xcb, 0xd5, 0x2d, 0xbb, 0x94, 0xfa, 0x82, 0x71, 0xb9, 0xd2, 0xb9, 0x33, + 0x43, 0x85, 0x14, 0x79, 0x08, 0x59, 0xec, 0x51, 0xd3, 0xdc, 0x13, 0x8e, 0x26, 0x8b, 0x32, 0x64, + 0x5d, 0x7c, 0x69, 0x74, 0xbf, 0x64, 0x2a, 0xd7, 0xcb, 0xe9, 0x17, 0x9c, 0xfb, 0x25, 0x1b, 0x68, + 0x50, 0x92, 0x64, 0x0b, 0x1f, 0x00, 0x76, 0xc4, 0x99, 0xa3, 0xce, 0xc0, 0xcd, 0x34, 0x58, 0x25, + 0x39, 0x07, 0x5a, 0x12, 0x59, 0x0c, 0xc2, 0xd6, 0x6b, 0x97, 0xab, 0x9a, 0x4a, 0x0b, 0x02, 0xb2, + 0x69, 0x8e, 0xe0, 0x14, 0xa5, 0x37, 0x03, 0x5f, 0x9e, 0x91, 0x74, 0x69, 0x64, 0xd3, 0xa4, 0x71, + 0x8a, 0x61, 0xd8, 0x77, 0xbb, 0x88, 0x56, 0xf3, 0xe7, 0x86, 0x41, 0x32, 0x6a, 0x61, 0x90, 0x84, + 0xf5, 0x79, 0x98, 0x13, 0x60, 0xca, 0xfa, 0x9b, 0x01, 0x45, 0x2d, 0x4f, 0x53, 0x54, 0xef, 0xfb, + 0x90, 0xdd, 0x63, 0xe2, 0xeb, 0x0b, 0x1a, 0xcf, 0x8b, 0xda, 0x65, 0xdc, 0xa6, 0x82, 0x8a, 0xed, + 0x67, 0xdb, 0x91, 0xad, 0xb5, 0x4c, 0x71, 0x88, 0x94, 0x17, 0xfc, 0x54, 0xa4, 0x2c, 0x4f, 0x71, + 0x48, 0x6e, 0x43, 0x7e, 0x9f, 0xb5, 0x7b, 0x91, 0xcb, 0x4f, 0x45, 0x12, 0x2a, 0xab, 0x55, 0xd1, + 0x94, 0x14, 0x4d, 0x94, 0x78, 0x9f, 0x83, 0xdc, 0x82, 0x42, 0xcc, 0xda, 0x11, 0xe3, 0xcc, 0x3f, + 0x56, 0xf5, 0x57, 0x56, 0xec, 0x11, 0xe3, 0x5b, 0xfe, 0x31, 0x1d, 0xac, 0x5b, 0x4f, 0xf1, 0x24, + 0x0f, 0xbc, 0x21, 0x90, 0xdd, 0xc0, 0x57, 0x26, 0xba, 0x51, 0xa6, 0x62, 0x8c, 0x0f, 0xfd, 0xad, + 0xf3, 0x1e, 0xfa, 0x5b, 0xc9, 0x43, 0x7f, 0xf8, 0x04, 0xe0, 0x85, 0xa7, 0x65, 0xc4, 0x7a, 0x02, + 0x85, 0xfe, 0x29, 0x25, 0x15, 0x98, 0xdd, 0x76, 0x94, 0xa5, 0xd9, 0x6d, 0x07, 0xfd, 0xde, 0x7a, + 0xbe, 0x2d, 0xac, 0xe4, 0x29, 0x0e, 0xfb, 0xb8, 0x24, 0xa3, 0xe1, 0x92, 0x35, 0x28, 0x0f, 0x1d, + 0x55, 0x64, 0xa2, 0xc1, 0x49, 0x9c, 0x6c, 0x19, 0xc7, 0xd2, 0x0d, 0x2f, 0x16, 0xba, 0x84, 0x1b, + 0x5e, 0x6c, 0x5d, 0x87, 0xf2, 0x50, 0x72, 0x91, 0x49, 0xbc, 0x99, 0x15, 0x7c, 0xc5, 0xf1, 0x0a, + 0x83, 0x85, 0x91, 0xcf, 0x68, 0xe4, 0x06, 0xe4, 0xe4, 0xe7, 0x9a, 0xea, 0x8c, 0x79, 0xe5, 0xeb, + 0x6f, 0x16, 0xdf, 0x1d, 0x61, 0x90, 0x8b, 0xc8, 0xb6, 0xde, 0xf3, 0x1d, 0x8f, 0x55, 0x8d, 0x89, + 0x6c, 0x72, 0xd1, 0xcc, 0xfe, 0xe6, 0x0f, 0x57, 0x67, 0x56, 0x6c, 0xb8, 0x34, 0xf6, 0x09, 0x88, + 0x5c, 0x87, 0xec, 0x3e, 0xf3, 0x3a, 0x89, 0x99, 0x31, 0x06, 0x5c, 0x24, 0xd7, 0x20, 0x43, 0xed, + 0x93, 0xaa, 0x61, 0xd6, 0xbe, 0xfe, 0x66, 0xf1, 0xf2, 0xf8, 0x77, 0x24, 0xfb, 0x44, 0x9a, 0x58, + 0xfd, 0x0b, 0x40, 0x61, 0x77, 0x77, 0x7d, 0x3d, 0x72, 0x9d, 0x2e, 0x23, 0xbf, 0x32, 0x80, 0x8c, + 0xbf, 0xae, 0xc9, 0xbd, 0xf4, 0x86, 0x30, 0xf9, 0x6b, 0x86, 0x79, 0xff, 0x82, 0x52, 0x0a, 0xdc, + 0x7c, 0x0e, 0x73, 0x02, 0x91, 0x93, 0x8f, 0xa6, 0x7c, 0x98, 0x99, 0xcb, 0xe7, 0x33, 0x2a, 0xdd, + 0x6d, 0xc8, 0x27, 0xa8, 0x96, 0xac, 0xa4, 0x6e, 0x6f, 0x08, 0xb4, 0x9b, 0xb7, 0xa6, 0xe2, 0x55, + 0x46, 0x7e, 0x0e, 0xf3, 0x0a, 0xac, 0x92, 0x9b, 0xe7, 0xc8, 0x0d, 0x60, 0xb3, 0xb9, 0x32, 0x0d, + 0xeb, 0xc0, 0x8d, 0x04, 0x94, 0xa6, 0xba, 0x31, 0x02, 0x79, 0x53, 0xdd, 0x18, 0x43, 0xb9, 0xed, + 0xc1, 0x53, 0x36, 0xd5, 0xc8, 0x08, 0xc4, 0x4d, 0x35, 0x32, 0x8a, 0x74, 0xc9, 0x4b, 0xc8, 0x22, + 0xd2, 0x25, 0x69, 0xbd, 0x5a, 0x83, 0xc2, 0x66, 0xda, 0x99, 0x18, 0x82, 0xc8, 0x3f, 0xc3, 0x3b, + 0x4d, 0x7c, 0xb5, 0x48, 0xbf, 0xcd, 0xb4, 0xaf, 0x9c, 0xe6, 0xcd, 0x29, 0x38, 0x07, 0xea, 0xd5, + 0x8b, 0x7f, 0x79, 0x8a, 0x4f, 0x8d, 0xe7, 0xab, 0x1f, 0xf9, 0xa8, 0x19, 0x40, 0x49, 0x87, 0x2a, + 0xa4, 0x9e, 0x22, 0x3a, 0x01, 0x2b, 0x9a, 0x8d, 0xa9, 0xf9, 0x95, 0xc1, 0xaf, 0xf0, 0xb9, 0x37, + 0x0c, 0x63, 0xc8, 0x6a, 0x6a, 0x38, 0x26, 0x02, 0x26, 0xf3, 0xee, 0x85, 0x64, 0x94, 0x71, 0x5b, + 0xc2, 0x24, 0x05, 0x85, 0x48, 0xfa, 0xad, 0xdf, 0x87, 0x53, 0xe6, 0x94, 0x7c, 0xcb, 0xc6, 0x1d, + 0x03, 0xcf, 0x19, 0x82, 0xec, 0x54, 0xdd, 0xda, 0xeb, 0x23, 0xf5, 0x9c, 0xe9, 0x68, 0x7d, 0xbd, + 0xf4, 0xdd, 0x9b, 0xab, 0xc6, 0xdf, 0xdf, 0x5c, 0x35, 0xfe, 0xf5, 0xe6, 0xaa, 0x71, 0x90, 0x13, + 0xff, 0xdd, 0xde, 0xfd, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x38, 0x3c, 0x7a, 0x9b, 0x44, 0x1f, + 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -5020,6 +5029,13 @@ func (m *NewContainerRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.NetworkConfigID) > 0 { + i -= len(m.NetworkConfigID) + copy(dAtA[i:], m.NetworkConfigID) + i = encodeVarintGateway(dAtA, i, uint64(len(m.NetworkConfigID))) + i-- + dAtA[i] = 0x42 + } if len(m.Hostname) > 0 { i -= len(m.Hostname) copy(dAtA[i:], m.Hostname) @@ -6482,6 +6498,10 @@ func (m *NewContainerRequest) Size() (n int) { if l > 0 { n += 1 + l + sovGateway(uint64(l)) } + l = len(m.NetworkConfigID) + if l > 0 { + n += 1 + l + sovGateway(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -11658,6 +11678,38 @@ func (m *NewContainerRequest) Unmarshal(dAtA []byte) error { } m.Hostname = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NetworkConfigID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGateway + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGateway + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGateway + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NetworkConfigID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGateway(dAtA[iNdEx:]) diff --git a/frontend/gateway/pb/gateway.proto b/frontend/gateway/pb/gateway.proto index c00d97391a43..2bedf95b9774 100644 --- a/frontend/gateway/pb/gateway.proto +++ b/frontend/gateway/pb/gateway.proto @@ -243,6 +243,7 @@ message NewContainerRequest { pb.WorkerConstraints constraints = 5; repeated pb.HostIP extraHosts = 6; string hostname = 7; + string networkConfigID = 8; } message NewContainerResponse{} diff --git a/go.mod b/go.mod index 14a4012e624f..9bb5dca3324f 100644 --- a/go.mod +++ b/go.mod @@ -46,6 +46,7 @@ require ( github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/moby/locker v1.0.1 github.com/moby/patternmatcher v0.5.0 + github.com/moby/sys/mount v0.3.3 github.com/moby/sys/mountinfo v0.6.2 github.com/moby/sys/signal v0.7.0 github.com/morikuni/aec v1.0.0 @@ -141,7 +142,6 @@ require ( github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/moby/sys/mount v0.3.3 // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/session/networks/attachable.go b/session/networks/attachable.go new file mode 100644 index 000000000000..4307cbbce7ba --- /dev/null +++ b/session/networks/attachable.go @@ -0,0 +1,30 @@ +package networks + +import ( + context "context" + + "github.com/moby/buildkit/session" + "google.golang.org/grpc" +) + +type ConfigFunc func(string) *Config + +type attachable struct { + getConfig ConfigFunc +} + +func NewConfigProvider(getConfig ConfigFunc) session.Attachable { + return &attachable{ + getConfig: getConfig, + } +} + +func (a *attachable) Register(srv *grpc.Server) { + RegisterNetworksServer(srv, a) +} + +func (a *attachable) GetNetwork(ctx context.Context, req *GetNetworkRequest) (*GetNetworkResponse, error) { + return &GetNetworkResponse{ + Config: a.getConfig(req.GetID()), // may be nil + }, nil +} diff --git a/session/networks/generate.go b/session/networks/generate.go new file mode 100644 index 000000000000..86d2f8f46007 --- /dev/null +++ b/session/networks/generate.go @@ -0,0 +1,3 @@ +package networks + +//go:generate protoc --gogoslick_out=plugins=grpc:. networks.proto diff --git a/session/networks/networks.go b/session/networks/networks.go new file mode 100644 index 000000000000..4affdc60f01a --- /dev/null +++ b/session/networks/networks.go @@ -0,0 +1,78 @@ +package networks + +import ( + context "context" + strings "strings" + + "github.com/moby/buildkit/session" +) + +func (config *Config) ExtraHosts() string { + out := "" + for _, ipHost := range config.IpHosts { + out += ipHost.Ip + " " + strings.Join(ipHost.Hosts, " ") + "\n" + } + return out +} + +func FromDNSConfig(dns *DNSConfig) *Config { + if dns == nil { + return &Config{} + } + + return &Config{ + Dns: &DNSConfig{ + Nameservers: dns.Nameservers, + Options: dns.Options, + SearchDomains: dns.SearchDomains, + }, + } +} + +func LoadConfig(ctx context.Context, c session.Caller, id string) (*Config, error) { + nw, err := NewNetworksClient(c.Conn()).GetNetwork(ctx, &GetNetworkRequest{ID: id}) + if err != nil { + return nil, err + } + + return nw.Config, nil +} + +func MergeConfig(ctx context.Context, c session.Caller, base *Config, id string) (*Config, error) { + custom, err := LoadConfig(ctx, c, id) + if err != nil { + return nil, err + } + + if custom == nil { + return base, nil + } + + cp := *base + + cp.IpHosts = append(custom.IpHosts, cp.IpHosts...) + + dns := custom.Dns + if dns != nil { + var dnsCp DNSConfig + if cp.Dns != nil { + dnsCp = *cp.Dns + } + + cp.Dns = &dnsCp + + if len(dns.Nameservers) > 0 { + cp.Dns.Nameservers = dns.Nameservers + } + + if len(dns.Options) > 0 { + cp.Dns.Options = dns.Options + } + + if len(dns.SearchDomains) > 0 { + cp.Dns.SearchDomains = dns.SearchDomains + } + } + + return &cp, nil +} diff --git a/session/networks/networks.pb.go b/session/networks/networks.pb.go new file mode 100644 index 000000000000..689ebca21879 --- /dev/null +++ b/session/networks/networks.pb.go @@ -0,0 +1,1630 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: networks.proto + +package networks + +import ( + context "context" + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" + reflect "reflect" + strings "strings" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type GetNetworkRequest struct { + ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` +} + +func (m *GetNetworkRequest) Reset() { *m = GetNetworkRequest{} } +func (*GetNetworkRequest) ProtoMessage() {} +func (*GetNetworkRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_e43f16ceb713dc88, []int{0} +} +func (m *GetNetworkRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetNetworkRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetNetworkRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetNetworkRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetNetworkRequest.Merge(m, src) +} +func (m *GetNetworkRequest) XXX_Size() int { + return m.Size() +} +func (m *GetNetworkRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetNetworkRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetNetworkRequest proto.InternalMessageInfo + +func (m *GetNetworkRequest) GetID() string { + if m != nil { + return m.ID + } + return "" +} + +type GetNetworkResponse struct { + Config *Config `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` +} + +func (m *GetNetworkResponse) Reset() { *m = GetNetworkResponse{} } +func (*GetNetworkResponse) ProtoMessage() {} +func (*GetNetworkResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_e43f16ceb713dc88, []int{1} +} +func (m *GetNetworkResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetNetworkResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetNetworkResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetNetworkResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetNetworkResponse.Merge(m, src) +} +func (m *GetNetworkResponse) XXX_Size() int { + return m.Size() +} +func (m *GetNetworkResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetNetworkResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetNetworkResponse proto.InternalMessageInfo + +func (m *GetNetworkResponse) GetConfig() *Config { + if m != nil { + return m.Config + } + return nil +} + +type Config struct { + Dns *DNSConfig `protobuf:"bytes,1,opt,name=dns,proto3" json:"dns,omitempty"` + IpHosts []*IPHosts `protobuf:"bytes,2,rep,name=ipHosts,proto3" json:"ipHosts,omitempty"` +} + +func (m *Config) Reset() { *m = Config{} } +func (*Config) ProtoMessage() {} +func (*Config) Descriptor() ([]byte, []int) { + return fileDescriptor_e43f16ceb713dc88, []int{2} +} +func (m *Config) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Config) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Config.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Config) XXX_Merge(src proto.Message) { + xxx_messageInfo_Config.Merge(m, src) +} +func (m *Config) XXX_Size() int { + return m.Size() +} +func (m *Config) XXX_DiscardUnknown() { + xxx_messageInfo_Config.DiscardUnknown(m) +} + +var xxx_messageInfo_Config proto.InternalMessageInfo + +func (m *Config) GetDns() *DNSConfig { + if m != nil { + return m.Dns + } + return nil +} + +func (m *Config) GetIpHosts() []*IPHosts { + if m != nil { + return m.IpHosts + } + return nil +} + +type DNSConfig struct { + Nameservers []string `protobuf:"bytes,1,rep,name=nameservers,proto3" json:"nameservers,omitempty"` + Options []string `protobuf:"bytes,2,rep,name=options,proto3" json:"options,omitempty"` + SearchDomains []string `protobuf:"bytes,3,rep,name=searchDomains,proto3" json:"searchDomains,omitempty"` +} + +func (m *DNSConfig) Reset() { *m = DNSConfig{} } +func (*DNSConfig) ProtoMessage() {} +func (*DNSConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_e43f16ceb713dc88, []int{3} +} +func (m *DNSConfig) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *DNSConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_DNSConfig.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *DNSConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_DNSConfig.Merge(m, src) +} +func (m *DNSConfig) XXX_Size() int { + return m.Size() +} +func (m *DNSConfig) XXX_DiscardUnknown() { + xxx_messageInfo_DNSConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_DNSConfig proto.InternalMessageInfo + +func (m *DNSConfig) GetNameservers() []string { + if m != nil { + return m.Nameservers + } + return nil +} + +func (m *DNSConfig) GetOptions() []string { + if m != nil { + return m.Options + } + return nil +} + +func (m *DNSConfig) GetSearchDomains() []string { + if m != nil { + return m.SearchDomains + } + return nil +} + +type IPHosts struct { + Ip string `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"` + Hosts []string `protobuf:"bytes,2,rep,name=hosts,proto3" json:"hosts,omitempty"` +} + +func (m *IPHosts) Reset() { *m = IPHosts{} } +func (*IPHosts) ProtoMessage() {} +func (*IPHosts) Descriptor() ([]byte, []int) { + return fileDescriptor_e43f16ceb713dc88, []int{4} +} +func (m *IPHosts) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *IPHosts) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_IPHosts.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *IPHosts) XXX_Merge(src proto.Message) { + xxx_messageInfo_IPHosts.Merge(m, src) +} +func (m *IPHosts) XXX_Size() int { + return m.Size() +} +func (m *IPHosts) XXX_DiscardUnknown() { + xxx_messageInfo_IPHosts.DiscardUnknown(m) +} + +var xxx_messageInfo_IPHosts proto.InternalMessageInfo + +func (m *IPHosts) GetIp() string { + if m != nil { + return m.Ip + } + return "" +} + +func (m *IPHosts) GetHosts() []string { + if m != nil { + return m.Hosts + } + return nil +} + +func init() { + proto.RegisterType((*GetNetworkRequest)(nil), "moby.buildkit.networks.v1.GetNetworkRequest") + proto.RegisterType((*GetNetworkResponse)(nil), "moby.buildkit.networks.v1.GetNetworkResponse") + proto.RegisterType((*Config)(nil), "moby.buildkit.networks.v1.Config") + proto.RegisterType((*DNSConfig)(nil), "moby.buildkit.networks.v1.DNSConfig") + proto.RegisterType((*IPHosts)(nil), "moby.buildkit.networks.v1.IPHosts") +} + +func init() { proto.RegisterFile("networks.proto", fileDescriptor_e43f16ceb713dc88) } + +var fileDescriptor_e43f16ceb713dc88 = []byte{ + // 368 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0xbd, 0x4e, 0x32, 0x41, + 0x14, 0xdd, 0x61, 0xf3, 0x01, 0x7b, 0xc9, 0x47, 0xf2, 0x4d, 0xbe, 0x62, 0xb5, 0x98, 0xe0, 0x4a, + 0x41, 0xa1, 0x6b, 0xc4, 0xc4, 0xc4, 0xc4, 0x58, 0xe8, 0x26, 0x4a, 0x83, 0x66, 0xed, 0xec, 0xf8, + 0x19, 0x65, 0x82, 0x3b, 0xb3, 0xee, 0x0c, 0x18, 0x1b, 0xe3, 0x23, 0xf8, 0x18, 0x3e, 0x8a, 0x25, + 0x25, 0xa5, 0x0c, 0x8d, 0x25, 0x8f, 0x60, 0xd8, 0x1f, 0xc4, 0x18, 0x89, 0xe5, 0x9c, 0x7b, 0xce, + 0xb9, 0xf7, 0x9e, 0x3b, 0x50, 0xe6, 0x54, 0xdd, 0x8b, 0xa8, 0x2f, 0xdd, 0x30, 0x12, 0x4a, 0xe0, + 0xb5, 0x40, 0xb4, 0x1f, 0xdc, 0xf6, 0x80, 0xdd, 0x76, 0xfb, 0x4c, 0xb9, 0x8b, 0xea, 0x70, 0xd7, + 0xd9, 0x84, 0x7f, 0xa7, 0x54, 0x35, 0x13, 0xc4, 0xa7, 0x77, 0x03, 0x2a, 0x15, 0x2e, 0x43, 0xae, + 0xe1, 0xd9, 0xa8, 0x82, 0x6a, 0x96, 0x9f, 0x6b, 0x78, 0xce, 0x39, 0xe0, 0x65, 0x92, 0x0c, 0x05, + 0x97, 0x14, 0x1f, 0x40, 0xbe, 0x23, 0xf8, 0x35, 0xbb, 0x89, 0x99, 0xa5, 0xfa, 0x86, 0xfb, 0x63, + 0x1b, 0xf7, 0x24, 0x26, 0xfa, 0xa9, 0xc0, 0x79, 0x84, 0x7c, 0x82, 0xe0, 0x7d, 0x30, 0xbb, 0x5c, + 0xa6, 0x0e, 0xd5, 0x15, 0x0e, 0x5e, 0xf3, 0x32, 0x35, 0x99, 0x0b, 0xf0, 0x21, 0x14, 0x58, 0x78, + 0x26, 0xa4, 0x92, 0x76, 0xae, 0x62, 0xd6, 0x4a, 0x75, 0x67, 0x85, 0xb6, 0x71, 0x11, 0x33, 0xfd, + 0x4c, 0xe2, 0x04, 0x60, 0x2d, 0xfc, 0x70, 0x05, 0x4a, 0xbc, 0x15, 0x50, 0x49, 0xa3, 0x21, 0x8d, + 0xe6, 0xa3, 0x98, 0x35, 0xcb, 0x5f, 0x86, 0xb0, 0x0d, 0x05, 0x11, 0x2a, 0x26, 0x78, 0xd2, 0xcc, + 0xf2, 0xb3, 0x27, 0xae, 0xc2, 0x5f, 0x49, 0x5b, 0x51, 0xa7, 0xe7, 0x89, 0xa0, 0xc5, 0xb8, 0xb4, + 0xcd, 0xb8, 0xfe, 0x15, 0x74, 0x76, 0xa0, 0x90, 0x8e, 0x30, 0x8f, 0x96, 0x85, 0x59, 0xb4, 0x2c, + 0xc4, 0xff, 0xe1, 0x4f, 0x6f, 0xb1, 0x85, 0xe5, 0x27, 0x8f, 0xfa, 0x00, 0x8a, 0x69, 0xda, 0x12, + 0x33, 0x80, 0xcf, 0xf0, 0xf1, 0xd6, 0x8a, 0x35, 0xbf, 0x1d, 0x72, 0x7d, 0xfb, 0x97, 0xec, 0xe4, + 0xa2, 0xc7, 0x47, 0xa3, 0x09, 0x31, 0xc6, 0x13, 0x62, 0xcc, 0x26, 0x04, 0x3d, 0x69, 0x82, 0x5e, + 0x34, 0x41, 0xaf, 0x9a, 0xa0, 0x91, 0x26, 0xe8, 0x4d, 0x13, 0xf4, 0xae, 0x89, 0x31, 0xd3, 0x04, + 0x3d, 0x4f, 0x89, 0x31, 0x9a, 0x12, 0x63, 0x3c, 0x25, 0xc6, 0x55, 0x31, 0x73, 0x6d, 0xe7, 0xe3, + 0xef, 0xb6, 0xf7, 0x11, 0x00, 0x00, 0xff, 0xff, 0x7a, 0x5d, 0xaa, 0x1a, 0x80, 0x02, 0x00, 0x00, +} + +func (this *GetNetworkRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*GetNetworkRequest) + if !ok { + that2, ok := that.(GetNetworkRequest) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.ID != that1.ID { + return false + } + return true +} +func (this *GetNetworkResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*GetNetworkResponse) + if !ok { + that2, ok := that.(GetNetworkResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Config.Equal(that1.Config) { + return false + } + return true +} +func (this *Config) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Config) + if !ok { + that2, ok := that.(Config) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Dns.Equal(that1.Dns) { + return false + } + if len(this.IpHosts) != len(that1.IpHosts) { + return false + } + for i := range this.IpHosts { + if !this.IpHosts[i].Equal(that1.IpHosts[i]) { + return false + } + } + return true +} +func (this *DNSConfig) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*DNSConfig) + if !ok { + that2, ok := that.(DNSConfig) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if len(this.Nameservers) != len(that1.Nameservers) { + return false + } + for i := range this.Nameservers { + if this.Nameservers[i] != that1.Nameservers[i] { + return false + } + } + if len(this.Options) != len(that1.Options) { + return false + } + for i := range this.Options { + if this.Options[i] != that1.Options[i] { + return false + } + } + if len(this.SearchDomains) != len(that1.SearchDomains) { + return false + } + for i := range this.SearchDomains { + if this.SearchDomains[i] != that1.SearchDomains[i] { + return false + } + } + return true +} +func (this *IPHosts) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*IPHosts) + if !ok { + that2, ok := that.(IPHosts) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Ip != that1.Ip { + return false + } + if len(this.Hosts) != len(that1.Hosts) { + return false + } + for i := range this.Hosts { + if this.Hosts[i] != that1.Hosts[i] { + return false + } + } + return true +} +func (this *GetNetworkRequest) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&networks.GetNetworkRequest{") + s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *GetNetworkResponse) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&networks.GetNetworkResponse{") + if this.Config != nil { + s = append(s, "Config: "+fmt.Sprintf("%#v", this.Config)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func (this *Config) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 6) + s = append(s, "&networks.Config{") + if this.Dns != nil { + s = append(s, "Dns: "+fmt.Sprintf("%#v", this.Dns)+",\n") + } + if this.IpHosts != nil { + s = append(s, "IpHosts: "+fmt.Sprintf("%#v", this.IpHosts)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func (this *DNSConfig) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 7) + s = append(s, "&networks.DNSConfig{") + s = append(s, "Nameservers: "+fmt.Sprintf("%#v", this.Nameservers)+",\n") + s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n") + s = append(s, "SearchDomains: "+fmt.Sprintf("%#v", this.SearchDomains)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *IPHosts) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 6) + s = append(s, "&networks.IPHosts{") + s = append(s, "Ip: "+fmt.Sprintf("%#v", this.Ip)+",\n") + s = append(s, "Hosts: "+fmt.Sprintf("%#v", this.Hosts)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func valueToGoStringNetworks(v interface{}, typ string) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// NetworksClient is the client API for Networks service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type NetworksClient interface { + GetNetwork(ctx context.Context, in *GetNetworkRequest, opts ...grpc.CallOption) (*GetNetworkResponse, error) +} + +type networksClient struct { + cc *grpc.ClientConn +} + +func NewNetworksClient(cc *grpc.ClientConn) NetworksClient { + return &networksClient{cc} +} + +func (c *networksClient) GetNetwork(ctx context.Context, in *GetNetworkRequest, opts ...grpc.CallOption) (*GetNetworkResponse, error) { + out := new(GetNetworkResponse) + err := c.cc.Invoke(ctx, "/moby.buildkit.networks.v1.Networks/GetNetwork", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// NetworksServer is the server API for Networks service. +type NetworksServer interface { + GetNetwork(context.Context, *GetNetworkRequest) (*GetNetworkResponse, error) +} + +// UnimplementedNetworksServer can be embedded to have forward compatible implementations. +type UnimplementedNetworksServer struct { +} + +func (*UnimplementedNetworksServer) GetNetwork(ctx context.Context, req *GetNetworkRequest) (*GetNetworkResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetNetwork not implemented") +} + +func RegisterNetworksServer(s *grpc.Server, srv NetworksServer) { + s.RegisterService(&_Networks_serviceDesc, srv) +} + +func _Networks_GetNetwork_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetNetworkRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NetworksServer).GetNetwork(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/moby.buildkit.networks.v1.Networks/GetNetwork", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NetworksServer).GetNetwork(ctx, req.(*GetNetworkRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Networks_serviceDesc = grpc.ServiceDesc{ + ServiceName: "moby.buildkit.networks.v1.Networks", + HandlerType: (*NetworksServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetNetwork", + Handler: _Networks_GetNetwork_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "networks.proto", +} + +func (m *GetNetworkRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetNetworkRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetNetworkRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ID) > 0 { + i -= len(m.ID) + copy(dAtA[i:], m.ID) + i = encodeVarintNetworks(dAtA, i, uint64(len(m.ID))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *GetNetworkResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetNetworkResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetNetworkResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Config != nil { + { + size, err := m.Config.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintNetworks(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Config) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Config) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Config) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.IpHosts) > 0 { + for iNdEx := len(m.IpHosts) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.IpHosts[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintNetworks(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Dns != nil { + { + size, err := m.Dns.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintNetworks(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *DNSConfig) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *DNSConfig) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DNSConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.SearchDomains) > 0 { + for iNdEx := len(m.SearchDomains) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.SearchDomains[iNdEx]) + copy(dAtA[i:], m.SearchDomains[iNdEx]) + i = encodeVarintNetworks(dAtA, i, uint64(len(m.SearchDomains[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if len(m.Options) > 0 { + for iNdEx := len(m.Options) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Options[iNdEx]) + copy(dAtA[i:], m.Options[iNdEx]) + i = encodeVarintNetworks(dAtA, i, uint64(len(m.Options[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if len(m.Nameservers) > 0 { + for iNdEx := len(m.Nameservers) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Nameservers[iNdEx]) + copy(dAtA[i:], m.Nameservers[iNdEx]) + i = encodeVarintNetworks(dAtA, i, uint64(len(m.Nameservers[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *IPHosts) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *IPHosts) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *IPHosts) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Hosts) > 0 { + for iNdEx := len(m.Hosts) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Hosts[iNdEx]) + copy(dAtA[i:], m.Hosts[iNdEx]) + i = encodeVarintNetworks(dAtA, i, uint64(len(m.Hosts[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if len(m.Ip) > 0 { + i -= len(m.Ip) + copy(dAtA[i:], m.Ip) + i = encodeVarintNetworks(dAtA, i, uint64(len(m.Ip))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintNetworks(dAtA []byte, offset int, v uint64) int { + offset -= sovNetworks(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GetNetworkRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ID) + if l > 0 { + n += 1 + l + sovNetworks(uint64(l)) + } + return n +} + +func (m *GetNetworkResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Config != nil { + l = m.Config.Size() + n += 1 + l + sovNetworks(uint64(l)) + } + return n +} + +func (m *Config) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Dns != nil { + l = m.Dns.Size() + n += 1 + l + sovNetworks(uint64(l)) + } + if len(m.IpHosts) > 0 { + for _, e := range m.IpHosts { + l = e.Size() + n += 1 + l + sovNetworks(uint64(l)) + } + } + return n +} + +func (m *DNSConfig) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Nameservers) > 0 { + for _, s := range m.Nameservers { + l = len(s) + n += 1 + l + sovNetworks(uint64(l)) + } + } + if len(m.Options) > 0 { + for _, s := range m.Options { + l = len(s) + n += 1 + l + sovNetworks(uint64(l)) + } + } + if len(m.SearchDomains) > 0 { + for _, s := range m.SearchDomains { + l = len(s) + n += 1 + l + sovNetworks(uint64(l)) + } + } + return n +} + +func (m *IPHosts) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Ip) + if l > 0 { + n += 1 + l + sovNetworks(uint64(l)) + } + if len(m.Hosts) > 0 { + for _, s := range m.Hosts { + l = len(s) + n += 1 + l + sovNetworks(uint64(l)) + } + } + return n +} + +func sovNetworks(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozNetworks(x uint64) (n int) { + return sovNetworks(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *GetNetworkRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&GetNetworkRequest{`, + `ID:` + fmt.Sprintf("%v", this.ID) + `,`, + `}`, + }, "") + return s +} +func (this *GetNetworkResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&GetNetworkResponse{`, + `Config:` + strings.Replace(this.Config.String(), "Config", "Config", 1) + `,`, + `}`, + }, "") + return s +} +func (this *Config) String() string { + if this == nil { + return "nil" + } + repeatedStringForIpHosts := "[]*IPHosts{" + for _, f := range this.IpHosts { + repeatedStringForIpHosts += strings.Replace(f.String(), "IPHosts", "IPHosts", 1) + "," + } + repeatedStringForIpHosts += "}" + s := strings.Join([]string{`&Config{`, + `Dns:` + strings.Replace(this.Dns.String(), "DNSConfig", "DNSConfig", 1) + `,`, + `IpHosts:` + repeatedStringForIpHosts + `,`, + `}`, + }, "") + return s +} +func (this *DNSConfig) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&DNSConfig{`, + `Nameservers:` + fmt.Sprintf("%v", this.Nameservers) + `,`, + `Options:` + fmt.Sprintf("%v", this.Options) + `,`, + `SearchDomains:` + fmt.Sprintf("%v", this.SearchDomains) + `,`, + `}`, + }, "") + return s +} +func (this *IPHosts) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&IPHosts{`, + `Ip:` + fmt.Sprintf("%v", this.Ip) + `,`, + `Hosts:` + fmt.Sprintf("%v", this.Hosts) + `,`, + `}`, + }, "") + return s +} +func valueToStringNetworks(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *GetNetworkRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowNetworks + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetNetworkRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetNetworkRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowNetworks + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthNetworks + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthNetworks + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipNetworks(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthNetworks + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetNetworkResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowNetworks + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetNetworkResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetNetworkResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Config", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowNetworks + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthNetworks + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthNetworks + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Config == nil { + m.Config = &Config{} + } + if err := m.Config.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipNetworks(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthNetworks + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Config) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowNetworks + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Config: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Config: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Dns", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowNetworks + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthNetworks + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthNetworks + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Dns == nil { + m.Dns = &DNSConfig{} + } + if err := m.Dns.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IpHosts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowNetworks + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthNetworks + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthNetworks + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.IpHosts = append(m.IpHosts, &IPHosts{}) + if err := m.IpHosts[len(m.IpHosts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipNetworks(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthNetworks + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *DNSConfig) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowNetworks + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: DNSConfig: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DNSConfig: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Nameservers", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowNetworks + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthNetworks + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthNetworks + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Nameservers = append(m.Nameservers, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowNetworks + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthNetworks + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthNetworks + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Options = append(m.Options, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SearchDomains", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowNetworks + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthNetworks + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthNetworks + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SearchDomains = append(m.SearchDomains, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipNetworks(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthNetworks + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *IPHosts) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowNetworks + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: IPHosts: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: IPHosts: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ip", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowNetworks + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthNetworks + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthNetworks + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ip = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hosts", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowNetworks + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthNetworks + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthNetworks + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hosts = append(m.Hosts, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipNetworks(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthNetworks + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipNetworks(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowNetworks + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowNetworks + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowNetworks + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthNetworks + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupNetworks + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthNetworks + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthNetworks = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowNetworks = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupNetworks = fmt.Errorf("proto: unexpected end of group") +) diff --git a/session/networks/networks.proto b/session/networks/networks.proto new file mode 100644 index 000000000000..c13652c7ff59 --- /dev/null +++ b/session/networks/networks.proto @@ -0,0 +1,33 @@ +syntax = "proto3"; + +package moby.buildkit.networks.v1; + +option go_package = "networks"; + +service Networks { + rpc GetNetwork(GetNetworkRequest) returns (GetNetworkResponse); +} + +message GetNetworkRequest { + string ID = 1; +} + +message GetNetworkResponse { + Config config = 1; +} + +message Config { + DNSConfig dns = 1; + repeated IPHosts ipHosts = 2; +} + +message DNSConfig { + repeated string nameservers = 1; + repeated string options = 2; + repeated string searchDomains = 3; +} + +message IPHosts { + string ip = 1; + repeated string hosts = 2; +} diff --git a/solver/llbsolver/ops/exec.go b/solver/llbsolver/ops/exec.go index eee0dd39fb6e..d22c1f1a1c59 100644 --- a/solver/llbsolver/ops/exec.go +++ b/solver/llbsolver/ops/exec.go @@ -5,6 +5,7 @@ import ( "context" "encoding/json" "fmt" + "net" "os" "path" "runtime" @@ -17,6 +18,7 @@ import ( resourcestypes "github.com/moby/buildkit/executor/resources/types" "github.com/moby/buildkit/frontend/gateway/container" "github.com/moby/buildkit/session" + "github.com/moby/buildkit/session/networks" "github.com/moby/buildkit/session/secrets" "github.com/moby/buildkit/solver" "github.com/moby/buildkit/solver/llbsolver/errdefs" @@ -346,6 +348,33 @@ func (e *ExecOp) Exec(ctx context.Context, g session.Group, inputs []solver.Resu RemoveMountStubsRecursive: e.op.Meta.RemoveMountStubsRecursive, } + netCfg, err := e.loadNetworkConfig(ctx, g) + if err != nil { + return nil, err + } + + if netCfg != nil { + for _, ipHosts := range netCfg.IpHosts { + for _, host := range ipHosts.Hosts { + ip := net.ParseIP(ipHosts.Ip) + if ip == nil { + return nil, errors.Errorf("invalid ip %q", ipHosts.Ip) + } + meta.ExtraHosts = append(meta.ExtraHosts, executor.HostIP{ + Host: host, + IP: ip, + }) + } + } + if netCfg.Dns != nil { + meta.DNS = &networks.DNSConfig{ + Nameservers: netCfg.Dns.Nameservers, + SearchDomains: netCfg.Dns.SearchDomains, + Options: netCfg.Dns.Options, + } + } + } + if e.op.Meta.ProxyEnv != nil { meta.Env = append(meta.Env, proxyEnvList(e.op.Meta.ProxyEnv)...) } @@ -458,6 +487,23 @@ func (e *ExecOp) loadSecretEnv(ctx context.Context, g session.Group) ([]string, return out, nil } +func (e *ExecOp) loadNetworkConfig(ctx context.Context, g session.Group) (*networks.Config, error) { + id := e.op.NetworkConfigID + if id == "" { + return nil, nil + } + var cfg *networks.Config + err := e.sm.Any(ctx, g, func(ctx context.Context, _ string, caller session.Caller) error { + var err error + cfg, err = networks.LoadConfig(ctx, caller, id) + return err + }) + if err != nil { + return nil, err + } + return cfg, nil +} + func (e *ExecOp) IsProvenanceProvider() { } diff --git a/solver/pb/attr.go b/solver/pb/attr.go index 85e7cce60ee8..f34b797ddb5d 100644 --- a/solver/pb/attr.go +++ b/solver/pb/attr.go @@ -6,6 +6,7 @@ const AttrAuthHeaderSecret = "git.authheadersecret" const AttrAuthTokenSecret = "git.authtokensecret" const AttrKnownSSHHosts = "git.knownsshhosts" const AttrMountSSHSock = "git.mountsshsock" + const AttrLocalSessionID = "local.session" const AttrLocalUniqueID = "local.unique" const AttrIncludePatterns = "local.includepattern" @@ -36,4 +37,6 @@ const AttrLocalDiffer = "local.differ" const AttrLocalDifferNone = "none" const AttrLocalDifferMetadata = "metadata" +const AttrNetworkConfigID = "network.config" + type IsFileAction = isFileAction_Action diff --git a/solver/pb/caps.go b/solver/pb/caps.go index 5e1963ff8faa..fcd28e99a16f 100644 --- a/solver/pb/caps.go +++ b/solver/pb/caps.go @@ -33,7 +33,7 @@ const ( CapSourceHTTP apicaps.CapID = "source.http" CapSourceHTTPChecksum apicaps.CapID = "source.http.checksum" CapSourceHTTPPerm apicaps.CapID = "source.http.perm" - CapSourceHTTPUIDGID apicaps.CapID = "soruce.http.uidgid" + CapSourceHTTPUIDGID apicaps.CapID = "soruce.http.uidgid" // NB: typo here, can it be changed? CapSourceOCILayout apicaps.CapID = "source.ocilayout" @@ -86,6 +86,8 @@ const ( CapSourceDateEpoch apicaps.CapID = "exporter.sourcedateepoch" CapSourcePolicy apicaps.CapID = "source.policy" + + CapNetworkConfigs apicaps.CapID = "networkconfigs" ) func init() { @@ -459,4 +461,10 @@ func init() { Enabled: true, Status: apicaps.CapStatusExperimental, }) + + Caps.Init(apicaps.Cap{ + ID: CapNetworkConfigs, + Enabled: true, + Status: apicaps.CapStatusExperimental, + }) } diff --git a/solver/pb/ops.pb.go b/solver/pb/ops.pb.go index aadff21b6474..374ca047fff7 100644 --- a/solver/pb/ops.pb.go +++ b/solver/pb/ops.pb.go @@ -421,11 +421,12 @@ var xxx_messageInfo_Input proto.InternalMessageInfo // ExecOp executes a command in a container. type ExecOp struct { - Meta *Meta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Mounts []*Mount `protobuf:"bytes,2,rep,name=mounts,proto3" json:"mounts,omitempty"` - Network NetMode `protobuf:"varint,3,opt,name=network,proto3,enum=pb.NetMode" json:"network,omitempty"` - Security SecurityMode `protobuf:"varint,4,opt,name=security,proto3,enum=pb.SecurityMode" json:"security,omitempty"` - Secretenv []*SecretEnv `protobuf:"bytes,5,rep,name=secretenv,proto3" json:"secretenv,omitempty"` + Meta *Meta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Mounts []*Mount `protobuf:"bytes,2,rep,name=mounts,proto3" json:"mounts,omitempty"` + Network NetMode `protobuf:"varint,3,opt,name=network,proto3,enum=pb.NetMode" json:"network,omitempty"` + Security SecurityMode `protobuf:"varint,4,opt,name=security,proto3,enum=pb.SecurityMode" json:"security,omitempty"` + Secretenv []*SecretEnv `protobuf:"bytes,5,rep,name=secretenv,proto3" json:"secretenv,omitempty"` + NetworkConfigID string `protobuf:"bytes,6,opt,name=networkConfigID,proto3" json:"networkConfigID,omitempty"` } func (m *ExecOp) Reset() { *m = ExecOp{} } @@ -492,6 +493,13 @@ func (m *ExecOp) GetSecretenv() []*SecretEnv { return nil } +func (m *ExecOp) GetNetworkConfigID() string { + if m != nil { + return m.NetworkConfigID + } + return "" +} + // Meta is a set of arguments for ExecOp. // Meta is unrelated to LLB metadata. // FIXME: rename (ExecContext? ExecArgs?) @@ -2850,169 +2858,170 @@ func init() { func init() { proto.RegisterFile("ops.proto", fileDescriptor_8de16154b2733812) } var fileDescriptor_8de16154b2733812 = []byte{ - // 2577 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x59, 0x4f, 0x6f, 0x5b, 0xc7, - 0x11, 0x17, 0xff, 0x93, 0x43, 0x89, 0x66, 0xd6, 0x4e, 0xc2, 0xa8, 0xae, 0xac, 0xbc, 0xa4, 0x81, - 0x2c, 0xdb, 0x12, 0xaa, 0x00, 0x71, 0x60, 0x04, 0x45, 0x25, 0x91, 0x8e, 0x18, 0xc7, 0xa2, 0xb0, - 0xb4, 0x9d, 0x1e, 0x0a, 0x18, 0x4f, 0x8f, 0x4b, 0xea, 0x41, 0xef, 0xbd, 0x7d, 0x78, 0x6f, 0x69, - 0x89, 0x3d, 0xf4, 0xd0, 0x53, 0x8f, 0x01, 0x0a, 0x14, 0xbd, 0x14, 0xfd, 0x12, 0x3d, 0xb6, 0xf7, - 0x00, 0xb9, 0xe4, 0xd0, 0x43, 0xd0, 0x43, 0x5a, 0x38, 0x97, 0x7e, 0x88, 0x16, 0x28, 0x66, 0x76, - 0xdf, 0x1f, 0x52, 0x32, 0x6c, 0xb7, 0x45, 0x4f, 0x9c, 0x37, 0xf3, 0xdb, 0xd9, 0xd9, 0xd9, 0x99, - 0x9d, 0xd9, 0x25, 0x34, 0x64, 0x18, 0x6f, 0x85, 0x91, 0x54, 0x92, 0x15, 0xc3, 0xe3, 0xd5, 0x3b, - 0x13, 0x57, 0x9d, 0x4c, 0x8f, 0xb7, 0x1c, 0xe9, 0x6f, 0x4f, 0xe4, 0x44, 0x6e, 0x93, 0xe8, 0x78, - 0x3a, 0xa6, 0x2f, 0xfa, 0x20, 0x4a, 0x0f, 0xb1, 0xfe, 0x51, 0x84, 0xe2, 0x20, 0x64, 0xef, 0x42, - 0xd5, 0x0d, 0xc2, 0xa9, 0x8a, 0x3b, 0x85, 0xf5, 0xd2, 0x46, 0x73, 0xa7, 0xb1, 0x15, 0x1e, 0x6f, - 0xf5, 0x91, 0xc3, 0x8d, 0x80, 0xad, 0x43, 0x59, 0x9c, 0x0b, 0xa7, 0x53, 0x5c, 0x2f, 0x6c, 0x34, - 0x77, 0x00, 0x01, 0xbd, 0x73, 0xe1, 0x0c, 0xc2, 0x83, 0x25, 0x4e, 0x12, 0xf6, 0x01, 0x54, 0x63, - 0x39, 0x8d, 0x1c, 0xd1, 0x29, 0x11, 0x66, 0x19, 0x31, 0x43, 0xe2, 0x10, 0xca, 0x48, 0x51, 0xd3, - 0xd8, 0xf5, 0x44, 0xa7, 0x9c, 0x69, 0xba, 0xef, 0x7a, 0x1a, 0x43, 0x12, 0xf6, 0x1e, 0x54, 0x8e, - 0xa7, 0xae, 0x37, 0xea, 0x54, 0x08, 0xd2, 0x44, 0xc8, 0x1e, 0x32, 0x08, 0xa3, 0x65, 0x08, 0xf2, - 0x45, 0x34, 0x11, 0x9d, 0x6a, 0x06, 0x7a, 0x88, 0x0c, 0x0d, 0x22, 0x19, 0xce, 0x35, 0x72, 0xc7, - 0xe3, 0x4e, 0x2d, 0x9b, 0xab, 0xeb, 0x8e, 0xc7, 0x7a, 0x2e, 0x94, 0xb0, 0x0d, 0xa8, 0x87, 0x9e, - 0xad, 0xc6, 0x32, 0xf2, 0x3b, 0x90, 0xd9, 0x7d, 0x64, 0x78, 0x3c, 0x95, 0xb2, 0xbb, 0xd0, 0x74, - 0x64, 0x10, 0xab, 0xc8, 0x76, 0x03, 0x15, 0x77, 0x9a, 0x04, 0x7e, 0x13, 0xc1, 0x5f, 0xc8, 0xe8, - 0x54, 0x44, 0xfb, 0x99, 0x90, 0xe7, 0x91, 0x7b, 0x65, 0x28, 0xca, 0xd0, 0xfa, 0x6d, 0x01, 0xea, - 0x89, 0x56, 0x66, 0xc1, 0xf2, 0x6e, 0xe4, 0x9c, 0xb8, 0x4a, 0x38, 0x6a, 0x1a, 0x89, 0x4e, 0x61, - 0xbd, 0xb0, 0xd1, 0xe0, 0x73, 0x3c, 0xd6, 0x82, 0xe2, 0x60, 0x48, 0xfe, 0x6e, 0xf0, 0xe2, 0x60, - 0xc8, 0x3a, 0x50, 0x7b, 0x62, 0x47, 0xae, 0x1d, 0x28, 0x72, 0x70, 0x83, 0x27, 0x9f, 0xec, 0x3a, - 0x34, 0x06, 0xc3, 0x27, 0x22, 0x8a, 0x5d, 0x19, 0x90, 0x5b, 0x1b, 0x3c, 0x63, 0xb0, 0x35, 0x80, - 0xc1, 0xf0, 0xbe, 0xb0, 0x51, 0x69, 0xdc, 0xa9, 0xac, 0x97, 0x36, 0x1a, 0x3c, 0xc7, 0xb1, 0x7e, - 0x09, 0x15, 0xda, 0x6a, 0xf6, 0x19, 0x54, 0x47, 0xee, 0x44, 0xc4, 0x4a, 0x9b, 0xb3, 0xb7, 0xf3, - 0xd5, 0x77, 0x37, 0x96, 0xfe, 0xfa, 0xdd, 0x8d, 0xcd, 0x5c, 0x4c, 0xc9, 0x50, 0x04, 0x8e, 0x0c, - 0x94, 0xed, 0x06, 0x22, 0x8a, 0xb7, 0x27, 0xf2, 0x8e, 0x1e, 0xb2, 0xd5, 0xa5, 0x1f, 0x6e, 0x34, - 0xb0, 0x9b, 0x50, 0x71, 0x83, 0x91, 0x38, 0x27, 0xfb, 0x4b, 0x7b, 0x57, 0x8d, 0xaa, 0xe6, 0x60, - 0xaa, 0xc2, 0xa9, 0xea, 0xa3, 0x88, 0x6b, 0x84, 0xf5, 0x75, 0x01, 0xaa, 0x3a, 0x94, 0xd8, 0x75, - 0x28, 0xfb, 0x42, 0xd9, 0x34, 0x7f, 0x73, 0xa7, 0xae, 0xb7, 0x54, 0xd9, 0x9c, 0xb8, 0x18, 0xa5, - 0xbe, 0x9c, 0xa2, 0xef, 0x8b, 0x59, 0x94, 0x3e, 0x44, 0x0e, 0x37, 0x02, 0xf6, 0x23, 0xa8, 0x05, - 0x42, 0x9d, 0xc9, 0xe8, 0x94, 0x7c, 0xd4, 0xd2, 0x61, 0x71, 0x28, 0xd4, 0x43, 0x39, 0x12, 0x3c, - 0x91, 0xb1, 0xdb, 0x50, 0x8f, 0x85, 0x33, 0x8d, 0x5c, 0x35, 0x23, 0x7f, 0xb5, 0x76, 0xda, 0x14, - 0xac, 0x86, 0x47, 0xe0, 0x14, 0xc1, 0x6e, 0x41, 0x23, 0x16, 0x4e, 0x24, 0x94, 0x08, 0x9e, 0x91, - 0xff, 0x9a, 0x3b, 0x2b, 0x06, 0x1e, 0x09, 0xd5, 0x0b, 0x9e, 0xf1, 0x4c, 0x6e, 0x7d, 0x5d, 0x84, - 0x32, 0xda, 0xcc, 0x18, 0x94, 0xed, 0x68, 0xa2, 0x33, 0xaa, 0xc1, 0x89, 0x66, 0x6d, 0x28, 0xa1, - 0x8e, 0x22, 0xb1, 0x90, 0x44, 0x8e, 0x73, 0x36, 0x32, 0x1b, 0x8a, 0x24, 0x8e, 0x9b, 0xc6, 0x22, - 0x32, 0xfb, 0x48, 0x34, 0xbb, 0x09, 0x8d, 0x30, 0x92, 0xe7, 0xb3, 0xa7, 0xda, 0x82, 0x2c, 0x4a, - 0x91, 0x89, 0x06, 0xd4, 0x43, 0x43, 0xb1, 0x4d, 0x00, 0x71, 0xae, 0x22, 0xfb, 0x40, 0xc6, 0x2a, - 0xee, 0x54, 0xc9, 0x5a, 0x8a, 0x7b, 0x64, 0xf4, 0x8f, 0x78, 0x4e, 0xca, 0x56, 0xa1, 0x7e, 0x22, - 0x63, 0x15, 0xd8, 0xbe, 0xa0, 0x0c, 0x69, 0xf0, 0xf4, 0x9b, 0x59, 0x50, 0x9d, 0x7a, 0xae, 0xef, - 0xaa, 0x4e, 0x23, 0xd3, 0xf1, 0x98, 0x38, 0xdc, 0x48, 0x30, 0x8a, 0x9d, 0x49, 0x24, 0xa7, 0xe1, - 0x91, 0x1d, 0x89, 0x40, 0x51, 0xfe, 0x34, 0xf8, 0x1c, 0x8f, 0x7d, 0x02, 0xef, 0x44, 0xc2, 0x97, - 0xcf, 0x04, 0x6d, 0xd4, 0x50, 0x4d, 0x8f, 0x63, 0x8e, 0x8e, 0x8d, 0xdd, 0x67, 0x82, 0x72, 0xa8, - 0xce, 0x5f, 0x0c, 0xb0, 0x6e, 0x43, 0x55, 0xdb, 0x8d, 0x6e, 0x41, 0xca, 0x64, 0x0a, 0xd1, 0x98, - 0x21, 0xfd, 0xa3, 0x24, 0x43, 0xfa, 0x47, 0x56, 0x17, 0xaa, 0xda, 0x42, 0x44, 0x1f, 0xe2, 0xaa, - 0x0c, 0x1a, 0x69, 0xe4, 0x0d, 0xe5, 0x58, 0xe9, 0x88, 0xe4, 0x44, 0x93, 0x56, 0x3b, 0xd2, 0xfe, - 0x2f, 0x71, 0xa2, 0xad, 0x07, 0xd0, 0x48, 0x77, 0x96, 0xa6, 0xe8, 0x1a, 0x35, 0xc5, 0x7e, 0x17, - 0x07, 0x90, 0xbb, 0xf4, 0xa4, 0x44, 0xa3, 0x1b, 0x65, 0xa8, 0x5c, 0x19, 0xd8, 0x1e, 0x29, 0xaa, - 0xf3, 0xf4, 0xdb, 0xfa, 0x5d, 0x09, 0x2a, 0xb4, 0x30, 0xb6, 0x81, 0x19, 0x11, 0x4e, 0xf5, 0x0a, - 0x4a, 0x7b, 0xcc, 0x64, 0x04, 0x50, 0xee, 0xa5, 0x09, 0x81, 0x79, 0xb8, 0x8a, 0xd1, 0xe9, 0x09, - 0x47, 0xc9, 0xc8, 0xcc, 0x93, 0x7e, 0xe3, 0xfc, 0x23, 0xcc, 0x50, 0x1d, 0x30, 0x44, 0xb3, 0x5b, - 0x50, 0x95, 0x94, 0x56, 0x14, 0x33, 0x2f, 0x48, 0x36, 0x03, 0x41, 0xe5, 0x91, 0xb0, 0x47, 0x32, - 0xf0, 0x66, 0x14, 0x49, 0x75, 0x9e, 0x7e, 0x63, 0xa0, 0x53, 0x1e, 0x3d, 0x9a, 0x85, 0xfa, 0x58, - 0x6d, 0xe9, 0x40, 0x7f, 0x98, 0x30, 0x79, 0x26, 0xc7, 0x83, 0xf3, 0x91, 0x1f, 0x8e, 0xe3, 0x41, - 0xa8, 0x3a, 0x57, 0xb3, 0x90, 0x4c, 0x78, 0x3c, 0x95, 0x22, 0xd2, 0xb1, 0x9d, 0x13, 0x81, 0xc8, - 0x6b, 0x19, 0x72, 0xdf, 0xf0, 0x78, 0x2a, 0xcd, 0x32, 0x0d, 0xa1, 0x6f, 0x12, 0x34, 0x97, 0x69, - 0x88, 0xcd, 0xe4, 0x18, 0xa1, 0xc3, 0xe1, 0x01, 0x22, 0xdf, 0xca, 0x4e, 0x77, 0xcd, 0xe1, 0x46, - 0xa2, 0x57, 0x1b, 0x4f, 0x3d, 0xd5, 0xef, 0x76, 0xde, 0xd6, 0xae, 0x4c, 0xbe, 0xad, 0xb5, 0x6c, - 0x01, 0xe8, 0xd6, 0xd8, 0xfd, 0x85, 0x8e, 0x97, 0x12, 0x27, 0xda, 0xea, 0x43, 0x3d, 0x31, 0xf1, - 0x42, 0x18, 0xdc, 0x81, 0x5a, 0x7c, 0x62, 0x47, 0x6e, 0x30, 0xa1, 0x1d, 0x6a, 0xed, 0x5c, 0x4d, - 0x57, 0x34, 0xd4, 0x7c, 0xb4, 0x22, 0xc1, 0x58, 0x32, 0x09, 0xa9, 0xcb, 0x74, 0xb5, 0xa1, 0x34, - 0x75, 0x47, 0xa4, 0x67, 0x85, 0x23, 0x89, 0x9c, 0x89, 0xab, 0x83, 0x72, 0x85, 0x23, 0x89, 0xf6, - 0xf9, 0x72, 0xa4, 0x6b, 0xe6, 0x0a, 0x27, 0x7a, 0x2e, 0xec, 0x2a, 0x0b, 0x61, 0xe7, 0x25, 0xbe, - 0xf9, 0xbf, 0xcc, 0xf6, 0x9b, 0x02, 0xd4, 0x93, 0x42, 0x8f, 0xe5, 0xc6, 0x1d, 0x89, 0x40, 0xb9, - 0x63, 0x57, 0x44, 0x66, 0xe2, 0x1c, 0x87, 0xdd, 0x81, 0x8a, 0xad, 0x54, 0x94, 0x1c, 0xe2, 0x6f, - 0xe7, 0xbb, 0x84, 0xad, 0x5d, 0x94, 0xf4, 0x02, 0x15, 0xcd, 0xb8, 0x46, 0xad, 0x7e, 0x0c, 0x90, - 0x31, 0xd1, 0xd6, 0x53, 0x31, 0x33, 0x5a, 0x91, 0x64, 0xd7, 0xa0, 0xf2, 0xcc, 0xf6, 0xa6, 0x49, - 0x46, 0xea, 0x8f, 0x7b, 0xc5, 0x8f, 0x0b, 0xd6, 0x9f, 0x8b, 0x50, 0x33, 0x5d, 0x03, 0xbb, 0x0d, - 0x35, 0xea, 0x1a, 0x8c, 0x45, 0x97, 0xa7, 0x5f, 0x02, 0x61, 0xdb, 0x69, 0x3b, 0x94, 0xb3, 0xd1, - 0xa8, 0xd2, 0x6d, 0x91, 0xb1, 0x31, 0x6b, 0x8e, 0x4a, 0x23, 0x31, 0x36, 0x7d, 0x4f, 0x8b, 0xba, - 0x0c, 0x31, 0x76, 0x03, 0x17, 0xfd, 0xc3, 0x51, 0xc4, 0x6e, 0x27, 0xab, 0x2e, 0x93, 0xc6, 0xb7, - 0xf2, 0x1a, 0x2f, 0x2e, 0xba, 0x0f, 0xcd, 0xdc, 0x34, 0x97, 0xac, 0xfa, 0xfd, 0xfc, 0xaa, 0xcd, - 0x94, 0xa4, 0x4e, 0x37, 0x6d, 0x99, 0x17, 0xfe, 0x0b, 0xff, 0x7d, 0x04, 0x90, 0xa9, 0x7c, 0xf5, - 0xe3, 0xcb, 0xfa, 0x53, 0x09, 0x60, 0x10, 0x62, 0x0d, 0x1c, 0xd9, 0x54, 0xb5, 0x97, 0xdd, 0x49, - 0x20, 0x23, 0xf1, 0x94, 0xd2, 0x9c, 0xc6, 0xd7, 0x79, 0x53, 0xf3, 0x28, 0x63, 0xd8, 0x2e, 0x34, - 0x47, 0x22, 0x76, 0x22, 0x97, 0x02, 0xca, 0x38, 0xfd, 0x06, 0xae, 0x29, 0xd3, 0xb3, 0xd5, 0xcd, - 0x10, 0xda, 0x57, 0xf9, 0x31, 0x6c, 0x07, 0x96, 0xc5, 0x79, 0x28, 0x23, 0x65, 0x66, 0xd1, 0xcd, - 0xe5, 0x15, 0xdd, 0xa6, 0x22, 0x9f, 0x66, 0xe2, 0x4d, 0x91, 0x7d, 0x30, 0x1b, 0xca, 0x8e, 0x1d, - 0xc6, 0xa6, 0xa4, 0x77, 0x16, 0xe6, 0xdb, 0xb7, 0x43, 0xed, 0xb4, 0xbd, 0x0f, 0x71, 0xad, 0xbf, - 0xfa, 0xdb, 0x8d, 0x5b, 0xb9, 0x3e, 0xc8, 0x97, 0xc7, 0xb3, 0x6d, 0x8a, 0x97, 0x53, 0x57, 0x6d, - 0x4f, 0x95, 0xeb, 0x6d, 0xdb, 0xa1, 0x8b, 0xea, 0x70, 0x60, 0xbf, 0xcb, 0x49, 0x35, 0xfb, 0x18, - 0x5a, 0x61, 0x24, 0x27, 0x91, 0x88, 0xe3, 0xa7, 0x54, 0x15, 0x4d, 0xb7, 0xfa, 0x86, 0xa9, 0xde, - 0x24, 0xf9, 0x14, 0x05, 0x7c, 0x25, 0xcc, 0x7f, 0xae, 0xfe, 0x04, 0xda, 0x8b, 0x2b, 0x7e, 0x9d, - 0xdd, 0x5b, 0xbd, 0x0b, 0x8d, 0x74, 0x05, 0x2f, 0x1b, 0x58, 0xcf, 0x6f, 0xfb, 0x1f, 0x0b, 0x50, - 0xd5, 0xf9, 0xc8, 0xee, 0x42, 0xc3, 0x93, 0x8e, 0x8d, 0x06, 0x24, 0x37, 0x83, 0x77, 0xb2, 0x74, - 0xdd, 0xfa, 0x3c, 0x91, 0xe9, 0xfd, 0xc8, 0xb0, 0x18, 0x9e, 0x6e, 0x30, 0x96, 0x49, 0xfe, 0xb4, - 0xb2, 0x41, 0xfd, 0x60, 0x2c, 0xb9, 0x16, 0xae, 0x3e, 0x80, 0xd6, 0xbc, 0x8a, 0x4b, 0xec, 0x7c, - 0x6f, 0x3e, 0xd0, 0xa9, 0x1a, 0xa4, 0x83, 0xf2, 0x66, 0xdf, 0x85, 0x46, 0xca, 0x67, 0x9b, 0x17, - 0x0d, 0x5f, 0xce, 0x8f, 0xcc, 0xd9, 0x6a, 0xfd, 0xba, 0x00, 0x90, 0xd9, 0x86, 0xe7, 0x1c, 0xde, - 0x41, 0x82, 0xac, 0x7b, 0x48, 0xbf, 0xa9, 0xf8, 0xda, 0xca, 0x26, 0x5b, 0x96, 0x39, 0xd1, 0x6c, - 0x0b, 0x60, 0x94, 0xe6, 0xfa, 0x0b, 0x4e, 0x80, 0x1c, 0x02, 0xf5, 0x7b, 0x76, 0x30, 0x99, 0xda, - 0x13, 0x61, 0x5a, 0xbc, 0xf4, 0xdb, 0x1a, 0x40, 0x3d, 0xb1, 0x90, 0xad, 0x43, 0x33, 0x36, 0x56, - 0x61, 0x1b, 0x8d, 0xa6, 0x54, 0x78, 0x9e, 0x85, 0xed, 0x70, 0x64, 0x07, 0x13, 0x31, 0xd7, 0x0e, - 0x73, 0xe4, 0x70, 0x23, 0xb0, 0xbe, 0x80, 0x0a, 0x31, 0x30, 0x7b, 0x63, 0x65, 0x47, 0xca, 0x74, - 0xd6, 0xba, 0x79, 0x94, 0x31, 0x99, 0xb4, 0x57, 0xc6, 0xf8, 0xe6, 0x1a, 0xc0, 0xde, 0xc7, 0x16, - 0x75, 0x64, 0xdc, 0x7d, 0x19, 0x0e, 0xc5, 0xd6, 0x27, 0x50, 0x4f, 0xd8, 0xe8, 0x15, 0xcf, 0x0d, - 0x84, 0x31, 0x91, 0x68, 0xbc, 0x91, 0x38, 0x27, 0x76, 0x64, 0x3b, 0x4a, 0xe8, 0x1e, 0xa6, 0xc2, - 0x33, 0x86, 0xf5, 0x1e, 0x34, 0x73, 0x49, 0x89, 0xb1, 0xf8, 0x84, 0xf6, 0x58, 0x1f, 0x0d, 0xfa, - 0xc3, 0xfa, 0x14, 0x56, 0xe6, 0x12, 0x04, 0x2b, 0x99, 0x3b, 0x4a, 0x2a, 0x99, 0xae, 0x52, 0x17, - 0x5a, 0x31, 0x06, 0xe5, 0x33, 0x61, 0x9f, 0x9a, 0x36, 0x8c, 0x68, 0xeb, 0x0f, 0x78, 0xf1, 0x4a, - 0xda, 0xe3, 0x1f, 0x02, 0x9c, 0x28, 0x15, 0x3e, 0xa5, 0x7e, 0xd9, 0x28, 0x6b, 0x20, 0x87, 0x10, - 0xec, 0x06, 0x34, 0xf1, 0x23, 0x36, 0x72, 0xad, 0x9a, 0x46, 0xc4, 0x1a, 0xf0, 0x03, 0x68, 0x8c, - 0xd3, 0xe1, 0x25, 0x13, 0x1f, 0xc9, 0xe8, 0x77, 0xa0, 0x1e, 0x48, 0x23, 0xd3, 0x7b, 0x5b, 0x0b, - 0x64, 0x3a, 0xce, 0xf6, 0x3c, 0x23, 0xab, 0xe8, 0x71, 0xb6, 0xe7, 0x91, 0xd0, 0xba, 0x05, 0x6f, - 0x5c, 0xb8, 0x42, 0xb2, 0xb7, 0xa0, 0x3a, 0x76, 0x3d, 0x45, 0x15, 0x0b, 0xaf, 0x0b, 0xe6, 0xcb, - 0xfa, 0x57, 0x01, 0x20, 0x8b, 0x2d, 0x4c, 0x19, 0x2c, 0x3d, 0x88, 0x59, 0xd6, 0xa5, 0xc6, 0x83, - 0xba, 0x6f, 0x0e, 0x31, 0x13, 0x19, 0xd7, 0xe7, 0xe3, 0x71, 0x2b, 0x39, 0xe3, 0xf4, 0xf1, 0xb6, - 0x63, 0x8e, 0xb7, 0xd7, 0xb9, 0xe6, 0xa5, 0x33, 0x50, 0x17, 0x96, 0xbf, 0xf5, 0x43, 0x96, 0xeb, - 0xdc, 0x48, 0x56, 0x1f, 0xc0, 0xca, 0xdc, 0x94, 0xaf, 0x58, 0xd0, 0xb2, 0xc3, 0x38, 0x9f, 0xe8, - 0x3b, 0x50, 0xd5, 0xcf, 0x05, 0x6c, 0x03, 0x6a, 0xb6, 0xa3, 0x73, 0x3c, 0x77, 0xce, 0xa0, 0x70, - 0x97, 0xd8, 0x3c, 0x11, 0x5b, 0x7f, 0x29, 0x02, 0x64, 0xfc, 0xd7, 0x68, 0xc5, 0xef, 0x41, 0x2b, - 0x16, 0x8e, 0x0c, 0x46, 0x76, 0x34, 0x23, 0xa9, 0xb9, 0xcf, 0x5e, 0x36, 0x64, 0x01, 0x99, 0x6b, - 0xcb, 0x4b, 0x2f, 0x6f, 0xcb, 0x37, 0xa0, 0xec, 0xc8, 0x70, 0x66, 0xea, 0x16, 0x9b, 0x5f, 0xc8, - 0xbe, 0x0c, 0x67, 0x07, 0x4b, 0x9c, 0x10, 0x6c, 0x0b, 0xaa, 0xfe, 0x29, 0x3d, 0xa0, 0xe8, 0x8b, - 0xe0, 0xb5, 0x79, 0xec, 0xc3, 0x53, 0xa4, 0x0f, 0x96, 0xb8, 0x41, 0xb1, 0x5b, 0x50, 0xf1, 0x4f, - 0x47, 0x6e, 0x64, 0x2a, 0xcf, 0xd5, 0x45, 0x78, 0xd7, 0x8d, 0xe8, 0xbd, 0x04, 0x31, 0xcc, 0x82, - 0x62, 0xe4, 0x9b, 0xd7, 0x92, 0xf6, 0x82, 0x37, 0xfd, 0x83, 0x25, 0x5e, 0x8c, 0xfc, 0xbd, 0x3a, - 0x54, 0xb5, 0x5f, 0xad, 0x7f, 0x96, 0xa0, 0x35, 0x6f, 0x25, 0xee, 0x6c, 0x1c, 0x39, 0xc9, 0xce, - 0xc6, 0x91, 0x93, 0xde, 0x58, 0x8a, 0xb9, 0x1b, 0x8b, 0x05, 0x15, 0x79, 0x16, 0x88, 0x28, 0xff, - 0x52, 0xb4, 0x7f, 0x22, 0xcf, 0x02, 0xec, 0x9a, 0xb5, 0x68, 0xae, 0x09, 0xad, 0x98, 0x26, 0xf4, - 0x7d, 0x58, 0x19, 0x4b, 0xcf, 0x93, 0x67, 0xc3, 0x99, 0xef, 0xb9, 0xc1, 0xa9, 0xe9, 0x44, 0xe7, - 0x99, 0x6c, 0x03, 0xae, 0x8c, 0xdc, 0x08, 0xcd, 0xd9, 0x97, 0x81, 0x12, 0x01, 0xdd, 0x83, 0x11, - 0xb7, 0xc8, 0x66, 0x9f, 0xc1, 0xba, 0xad, 0x94, 0xf0, 0x43, 0xf5, 0x38, 0x08, 0x6d, 0xe7, 0xb4, - 0x2b, 0x1d, 0xca, 0x42, 0x3f, 0xb4, 0x95, 0x7b, 0xec, 0x7a, 0xae, 0x9a, 0x91, 0x33, 0xea, 0xfc, - 0xa5, 0x38, 0xf6, 0x01, 0xb4, 0x9c, 0x48, 0xd8, 0x4a, 0x74, 0x45, 0xac, 0x8e, 0x6c, 0x75, 0xd2, - 0xa9, 0xd3, 0xc8, 0x05, 0x2e, 0xae, 0xc1, 0x46, 0x6b, 0xbf, 0x70, 0xbd, 0x91, 0x83, 0x77, 0xcf, - 0x86, 0x5e, 0xc3, 0x1c, 0x93, 0x6d, 0x01, 0x23, 0x46, 0xcf, 0x0f, 0xd5, 0x2c, 0x85, 0x02, 0x41, - 0x2f, 0x91, 0xe0, 0x81, 0xab, 0x5c, 0x5f, 0xc4, 0xca, 0xf6, 0x43, 0xba, 0x56, 0x97, 0x78, 0xc6, - 0x60, 0x37, 0xa1, 0xed, 0x06, 0x8e, 0x37, 0x1d, 0x89, 0xa7, 0x21, 0x2e, 0x24, 0x0a, 0xe2, 0xce, - 0x32, 0x9d, 0x2a, 0x57, 0x0c, 0xff, 0xc8, 0xb0, 0x11, 0x2a, 0xce, 0x17, 0xa0, 0x2b, 0x1a, 0x6a, - 0xf8, 0x09, 0xd4, 0xfa, 0xb2, 0x00, 0xed, 0xc5, 0xc0, 0xc3, 0x6d, 0x0b, 0x71, 0xf1, 0xe6, 0xe6, - 0x8d, 0x74, 0xba, 0x95, 0xc5, 0xdc, 0x56, 0x26, 0xb5, 0xb4, 0x94, 0xab, 0xa5, 0x69, 0x58, 0x94, - 0x5f, 0x1c, 0x16, 0x73, 0x0b, 0xad, 0x2c, 0x2c, 0xd4, 0xfa, 0x7d, 0x01, 0xae, 0x2c, 0x04, 0xf7, - 0x2b, 0x5b, 0xb4, 0x0e, 0x4d, 0xdf, 0x3e, 0x15, 0xfa, 0xdd, 0x22, 0x36, 0x25, 0x24, 0xcf, 0xfa, - 0x1f, 0xd8, 0x17, 0xc0, 0x72, 0x3e, 0xa3, 0x2e, 0xb5, 0x2d, 0x09, 0x90, 0x43, 0xa9, 0xee, 0xcb, - 0xa9, 0xa9, 0xc5, 0x49, 0x80, 0x24, 0xcc, 0x8b, 0x61, 0x54, 0xba, 0x24, 0x8c, 0xac, 0x43, 0xa8, - 0x27, 0x06, 0xb2, 0x1b, 0xe6, 0x61, 0xa9, 0x90, 0xbd, 0x97, 0x3e, 0x8e, 0x45, 0x84, 0xb6, 0xeb, - 0x57, 0xa6, 0x77, 0xa1, 0xa2, 0x7b, 0xd4, 0xe2, 0x45, 0x84, 0x96, 0x58, 0x43, 0xa8, 0x19, 0x0e, - 0xdb, 0x84, 0xea, 0xf1, 0x2c, 0x7d, 0x64, 0x31, 0xc7, 0x05, 0x7e, 0x8f, 0x0c, 0x02, 0xcf, 0x20, - 0x8d, 0x60, 0xd7, 0xa0, 0x7c, 0x3c, 0xeb, 0x77, 0xf5, 0xad, 0x13, 0x4f, 0x32, 0xfc, 0xda, 0xab, - 0x6a, 0x83, 0xac, 0xcf, 0x61, 0x39, 0x3f, 0x2e, 0x2d, 0xec, 0x85, 0x5c, 0x61, 0x4f, 0x8f, 0xec, - 0xe2, 0xcb, 0xae, 0x1f, 0x1f, 0x01, 0xd0, 0x33, 0xf0, 0xeb, 0x5e, 0x5b, 0x7e, 0x0c, 0x35, 0xf3, - 0x7c, 0xcc, 0x3e, 0x58, 0x78, 0x0e, 0x6f, 0xa5, 0x6f, 0xcb, 0x73, 0x6f, 0xe2, 0xd6, 0x3d, 0x6c, - 0x60, 0xcf, 0x44, 0xd4, 0x75, 0xc7, 0xe3, 0xd7, 0x9d, 0xee, 0x1e, 0xb4, 0x1e, 0x87, 0xe1, 0x7f, - 0x36, 0xf6, 0xe7, 0x50, 0xd5, 0xaf, 0xd8, 0x38, 0xc6, 0x43, 0x0b, 0xcc, 0x1e, 0x30, 0xdd, 0xe4, - 0xe6, 0x4d, 0xe2, 0x1a, 0x80, 0xc8, 0x29, 0xce, 0x67, 0x36, 0x97, 0x90, 0xf3, 0x06, 0x70, 0x0d, - 0xd8, 0xdc, 0x80, 0x9a, 0x79, 0x30, 0x65, 0x0d, 0xa8, 0x3c, 0x3e, 0x1c, 0xf6, 0x1e, 0xb5, 0x97, - 0x58, 0x1d, 0xca, 0x07, 0x83, 0xe1, 0xa3, 0x76, 0x01, 0xa9, 0xc3, 0xc1, 0x61, 0xaf, 0x5d, 0xdc, - 0xbc, 0x09, 0xcb, 0xf9, 0x27, 0x53, 0xd6, 0x84, 0xda, 0x70, 0xf7, 0xb0, 0xbb, 0x37, 0xf8, 0x59, - 0x7b, 0x89, 0x2d, 0x43, 0xbd, 0x7f, 0x38, 0xec, 0xed, 0x3f, 0xe6, 0xbd, 0x76, 0x61, 0xf3, 0xa7, - 0xd0, 0x48, 0x5f, 0x91, 0x50, 0xc3, 0x5e, 0xff, 0xb0, 0xdb, 0x5e, 0x62, 0x00, 0xd5, 0x61, 0x6f, - 0x9f, 0xf7, 0x50, 0x6f, 0x0d, 0x4a, 0xc3, 0xe1, 0x41, 0xbb, 0x88, 0xb3, 0xee, 0xef, 0xee, 0x1f, - 0xf4, 0xda, 0x25, 0x24, 0x1f, 0x3d, 0x3c, 0xba, 0x3f, 0x6c, 0x97, 0x37, 0x3f, 0x82, 0x2b, 0x0b, - 0xef, 0x2b, 0x34, 0xfa, 0x60, 0x97, 0xf7, 0x50, 0x53, 0x13, 0x6a, 0x47, 0xbc, 0xff, 0x64, 0xf7, - 0x51, 0xaf, 0x5d, 0x40, 0xc1, 0xe7, 0x83, 0xfd, 0x07, 0xbd, 0x6e, 0xbb, 0xb8, 0x77, 0xfd, 0xab, - 0xe7, 0x6b, 0x85, 0x6f, 0x9e, 0xaf, 0x15, 0xbe, 0x7d, 0xbe, 0x56, 0xf8, 0xfb, 0xf3, 0xb5, 0xc2, - 0x97, 0xdf, 0xaf, 0x2d, 0x7d, 0xf3, 0xfd, 0xda, 0xd2, 0xb7, 0xdf, 0xaf, 0x2d, 0x1d, 0x57, 0xe9, - 0x7f, 0x90, 0x0f, 0xff, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xd5, 0x3c, 0x38, 0x7a, 0x47, 0x19, 0x00, - 0x00, + // 2596 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x59, 0x4f, 0x6f, 0x1b, 0xc7, + 0x15, 0x17, 0xff, 0x93, 0x8f, 0x12, 0xcd, 0x8c, 0x9d, 0x84, 0x51, 0x5d, 0x59, 0xd9, 0xa4, 0x81, + 0x2c, 0xdb, 0x12, 0xaa, 0x00, 0x71, 0x60, 0x04, 0x45, 0x25, 0x91, 0x8e, 0x18, 0xc7, 0xa2, 0x30, + 0xb4, 0x9d, 0x1e, 0x0a, 0x18, 0xab, 0xe5, 0x90, 0x5a, 0x68, 0x77, 0x67, 0xb1, 0x3b, 0xb4, 0xc4, + 0x1e, 0x7a, 0xe8, 0xa9, 0xc7, 0x00, 0x05, 0x8a, 0x5e, 0x8a, 0x7e, 0x89, 0x1e, 0xdb, 0x7b, 0x80, + 0x5e, 0x72, 0xe8, 0x21, 0xe8, 0x21, 0x2d, 0x9c, 0x4b, 0xbf, 0x40, 0x6f, 0x2d, 0x50, 0xbc, 0x37, + 0xb3, 0x7f, 0x48, 0xc9, 0xb0, 0xdd, 0x16, 0x3d, 0x71, 0xf6, 0xf7, 0x7e, 0xf3, 0xe6, 0xcd, 0xcc, + 0x7b, 0xf3, 0xde, 0x0c, 0xa1, 0x21, 0xc3, 0x78, 0x2b, 0x8c, 0xa4, 0x92, 0xac, 0x18, 0x1e, 0xaf, + 0xde, 0x99, 0xb8, 0xea, 0x64, 0x7a, 0xbc, 0xe5, 0x48, 0x7f, 0x7b, 0x22, 0x27, 0x72, 0x9b, 0x44, + 0xc7, 0xd3, 0x31, 0x7d, 0xd1, 0x07, 0xb5, 0x74, 0x17, 0xeb, 0xef, 0x45, 0x28, 0x0e, 0x42, 0xf6, + 0x2e, 0x54, 0xdd, 0x20, 0x9c, 0xaa, 0xb8, 0x53, 0x58, 0x2f, 0x6d, 0x34, 0x77, 0x1a, 0x5b, 0xe1, + 0xf1, 0x56, 0x1f, 0x11, 0x6e, 0x04, 0x6c, 0x1d, 0xca, 0xe2, 0x5c, 0x38, 0x9d, 0xe2, 0x7a, 0x61, + 0xa3, 0xb9, 0x03, 0x48, 0xe8, 0x9d, 0x0b, 0x67, 0x10, 0x1e, 0x2c, 0x71, 0x92, 0xb0, 0x0f, 0xa0, + 0x1a, 0xcb, 0x69, 0xe4, 0x88, 0x4e, 0x89, 0x38, 0xcb, 0xc8, 0x19, 0x12, 0x42, 0x2c, 0x23, 0x45, + 0x4d, 0x63, 0xd7, 0x13, 0x9d, 0x72, 0xa6, 0xe9, 0xbe, 0xeb, 0x69, 0x0e, 0x49, 0xd8, 0x7b, 0x50, + 0x39, 0x9e, 0xba, 0xde, 0xa8, 0x53, 0x21, 0x4a, 0x13, 0x29, 0x7b, 0x08, 0x10, 0x47, 0xcb, 0x90, + 0xe4, 0x8b, 0x68, 0x22, 0x3a, 0xd5, 0x8c, 0xf4, 0x10, 0x01, 0x4d, 0x22, 0x19, 0x8e, 0x35, 0x72, + 0xc7, 0xe3, 0x4e, 0x2d, 0x1b, 0xab, 0xeb, 0x8e, 0xc7, 0x7a, 0x2c, 0x94, 0xb0, 0x0d, 0xa8, 0x87, + 0x9e, 0xad, 0xc6, 0x32, 0xf2, 0x3b, 0x90, 0xd9, 0x7d, 0x64, 0x30, 0x9e, 0x4a, 0xd9, 0x5d, 0x68, + 0x3a, 0x32, 0x88, 0x55, 0x64, 0xbb, 0x81, 0x8a, 0x3b, 0x4d, 0x22, 0xbf, 0x89, 0xe4, 0x2f, 0x64, + 0x74, 0x2a, 0xa2, 0xfd, 0x4c, 0xc8, 0xf3, 0xcc, 0xbd, 0x32, 0x14, 0x65, 0x68, 0xfd, 0xba, 0x00, + 0xf5, 0x44, 0x2b, 0xb3, 0x60, 0x79, 0x37, 0x72, 0x4e, 0x5c, 0x25, 0x1c, 0x35, 0x8d, 0x44, 0xa7, + 0xb0, 0x5e, 0xd8, 0x68, 0xf0, 0x39, 0x8c, 0xb5, 0xa0, 0x38, 0x18, 0xd2, 0x7a, 0x37, 0x78, 0x71, + 0x30, 0x64, 0x1d, 0xa8, 0x3d, 0xb1, 0x23, 0xd7, 0x0e, 0x14, 0x2d, 0x70, 0x83, 0x27, 0x9f, 0xec, + 0x3a, 0x34, 0x06, 0xc3, 0x27, 0x22, 0x8a, 0x5d, 0x19, 0xd0, 0xb2, 0x36, 0x78, 0x06, 0xb0, 0x35, + 0x80, 0xc1, 0xf0, 0xbe, 0xb0, 0x51, 0x69, 0xdc, 0xa9, 0xac, 0x97, 0x36, 0x1a, 0x3c, 0x87, 0x58, + 0x3f, 0x87, 0x0a, 0x6d, 0x35, 0xfb, 0x0c, 0xaa, 0x23, 0x77, 0x22, 0x62, 0xa5, 0xcd, 0xd9, 0xdb, + 0xf9, 0xea, 0xdb, 0x1b, 0x4b, 0x7f, 0xf9, 0xf6, 0xc6, 0x66, 0xce, 0xa7, 0x64, 0x28, 0x02, 0x47, + 0x06, 0xca, 0x76, 0x03, 0x11, 0xc5, 0xdb, 0x13, 0x79, 0x47, 0x77, 0xd9, 0xea, 0xd2, 0x0f, 0x37, + 0x1a, 0xd8, 0x4d, 0xa8, 0xb8, 0xc1, 0x48, 0x9c, 0x93, 0xfd, 0xa5, 0xbd, 0xab, 0x46, 0x55, 0x73, + 0x30, 0x55, 0xe1, 0x54, 0xf5, 0x51, 0xc4, 0x35, 0xc3, 0xfa, 0x47, 0x01, 0xaa, 0xda, 0x95, 0xd8, + 0x75, 0x28, 0xfb, 0x42, 0xd9, 0x34, 0x7e, 0x73, 0xa7, 0xae, 0xb7, 0x54, 0xd9, 0x9c, 0x50, 0xf4, + 0x52, 0x5f, 0x4e, 0x71, 0xed, 0x8b, 0x99, 0x97, 0x3e, 0x44, 0x84, 0x1b, 0x01, 0xfb, 0x01, 0xd4, + 0x02, 0xa1, 0xce, 0x64, 0x74, 0x4a, 0x6b, 0xd4, 0xd2, 0x6e, 0x71, 0x28, 0xd4, 0x43, 0x39, 0x12, + 0x3c, 0x91, 0xb1, 0xdb, 0x50, 0x8f, 0x85, 0x33, 0x8d, 0x5c, 0x35, 0xa3, 0xf5, 0x6a, 0xed, 0xb4, + 0xc9, 0x59, 0x0d, 0x46, 0xe4, 0x94, 0xc1, 0x6e, 0x41, 0x23, 0x16, 0x4e, 0x24, 0x94, 0x08, 0x9e, + 0xd1, 0xfa, 0x35, 0x77, 0x56, 0x0c, 0x3d, 0x12, 0xaa, 0x17, 0x3c, 0xe3, 0x99, 0x9c, 0x6d, 0xc0, + 0x15, 0x33, 0xca, 0xbe, 0x0c, 0xc6, 0xee, 0xa4, 0xdf, 0x25, 0x07, 0x6d, 0xf0, 0x45, 0xd8, 0xfa, + 0x53, 0x11, 0xca, 0x38, 0x3b, 0xc6, 0xa0, 0x6c, 0x47, 0x13, 0x1d, 0x7b, 0x0d, 0x4e, 0x6d, 0xd6, + 0x86, 0x12, 0x8e, 0x56, 0x24, 0x08, 0x9b, 0x88, 0x38, 0x67, 0x23, 0xb3, 0xf5, 0xd8, 0xc4, 0x7e, + 0xd3, 0x58, 0x44, 0x66, 0xc7, 0xa9, 0xcd, 0x6e, 0x42, 0x23, 0x8c, 0xe4, 0xf9, 0xec, 0xa9, 0xb6, + 0x35, 0xf3, 0x67, 0x04, 0xd1, 0xd4, 0x7a, 0x68, 0x5a, 0x6c, 0x13, 0x40, 0x9c, 0xab, 0xc8, 0x3e, + 0x90, 0xb1, 0x8a, 0x3b, 0x55, 0x9a, 0x17, 0x45, 0x08, 0x02, 0xfd, 0x23, 0x9e, 0x93, 0xb2, 0x55, + 0xa8, 0x9f, 0xc8, 0x58, 0x05, 0xb6, 0x2f, 0x28, 0x96, 0x1a, 0x3c, 0xfd, 0x66, 0x16, 0x54, 0xa7, + 0x9e, 0xeb, 0xbb, 0xaa, 0xd3, 0xc8, 0x74, 0x3c, 0x26, 0x84, 0x1b, 0x09, 0xfa, 0xbb, 0x33, 0x89, + 0xe4, 0x34, 0x3c, 0xb2, 0x23, 0x11, 0x28, 0x8a, 0xb4, 0x06, 0x9f, 0xc3, 0xd8, 0x27, 0xf0, 0x4e, + 0x24, 0x7c, 0xf9, 0x4c, 0xd0, 0x96, 0x0e, 0xd5, 0xf4, 0x38, 0xe6, 0xb8, 0x05, 0xb1, 0xfb, 0x4c, + 0x50, 0xb4, 0xd5, 0xf9, 0x8b, 0x09, 0xd6, 0x6d, 0xa8, 0x6a, 0xbb, 0x71, 0x59, 0xb0, 0x65, 0x62, + 0x8a, 0xda, 0x18, 0x4b, 0xfd, 0xa3, 0x24, 0x96, 0xfa, 0x47, 0x56, 0x17, 0xaa, 0xda, 0x42, 0x64, + 0x1f, 0xe2, 0xac, 0x0c, 0x1b, 0xdb, 0x88, 0x0d, 0xe5, 0x58, 0x69, 0xdf, 0xe5, 0xd4, 0x26, 0xad, + 0x76, 0xa4, 0xd7, 0xbf, 0xc4, 0xa9, 0x6d, 0x3d, 0x80, 0x46, 0xea, 0x03, 0x34, 0x44, 0xd7, 0xa8, + 0x29, 0xf6, 0xbb, 0xd8, 0x81, 0x96, 0x4b, 0x0f, 0x4a, 0x6d, 0x5c, 0x46, 0x19, 0x2a, 0x57, 0x06, + 0xb6, 0x47, 0x8a, 0xea, 0x3c, 0xfd, 0xb6, 0x7e, 0x53, 0x82, 0x0a, 0x4d, 0x8c, 0x6d, 0x60, 0xec, + 0x84, 0x53, 0x3d, 0x83, 0xd2, 0x1e, 0x33, 0xb1, 0x03, 0x14, 0xa5, 0x69, 0xe8, 0x60, 0xc4, 0xae, + 0xa2, 0x1f, 0x7b, 0xc2, 0x51, 0x32, 0x32, 0xe3, 0xa4, 0xdf, 0x38, 0xfe, 0x08, 0x63, 0x59, 0x3b, + 0x0c, 0xb5, 0xd9, 0x2d, 0xa8, 0x4a, 0x0a, 0x40, 0xf2, 0x99, 0x17, 0x84, 0xa5, 0xa1, 0xa0, 0xf2, + 0x48, 0xd8, 0x23, 0x19, 0x78, 0x33, 0xf2, 0xa4, 0x3a, 0x4f, 0xbf, 0x31, 0x24, 0x28, 0xe2, 0x1e, + 0xcd, 0x42, 0x7d, 0x00, 0xb7, 0x74, 0x48, 0x3c, 0x4c, 0x40, 0x9e, 0xc9, 0xf1, 0x88, 0x7d, 0xe4, + 0x87, 0xe3, 0x78, 0x10, 0xaa, 0xce, 0xd5, 0xcc, 0x25, 0x13, 0x8c, 0xa7, 0x52, 0x64, 0x3a, 0xb6, + 0x73, 0x22, 0x90, 0x79, 0x2d, 0x63, 0xee, 0x1b, 0x8c, 0xa7, 0xd2, 0x2c, 0x26, 0x91, 0xfa, 0x26, + 0x51, 0x73, 0x31, 0x89, 0xdc, 0x4c, 0x8e, 0x1e, 0x3a, 0x1c, 0x1e, 0x20, 0xf3, 0xad, 0x2c, 0x0f, + 0x68, 0x84, 0x1b, 0x89, 0x9e, 0x6d, 0x3c, 0xf5, 0x54, 0xbf, 0xdb, 0x79, 0x5b, 0x2f, 0x65, 0xf2, + 0x6d, 0xad, 0x65, 0x13, 0xc0, 0x65, 0x8d, 0xdd, 0x9f, 0x69, 0x7f, 0x29, 0x71, 0x6a, 0x5b, 0x7d, + 0xa8, 0x27, 0x26, 0x5e, 0x70, 0x83, 0x3b, 0x50, 0x8b, 0x4f, 0xec, 0xc8, 0x0d, 0x26, 0xb4, 0x43, + 0xad, 0x9d, 0xab, 0xe9, 0x8c, 0x86, 0x1a, 0x47, 0x2b, 0x12, 0x8e, 0x25, 0x13, 0x97, 0xba, 0x4c, + 0x57, 0x1b, 0x4a, 0x53, 0x77, 0x44, 0x7a, 0x56, 0x38, 0x36, 0x11, 0x99, 0xb8, 0xda, 0x29, 0x57, + 0x38, 0x36, 0xd1, 0x3e, 0x5f, 0x8e, 0x74, 0x76, 0x5d, 0xe1, 0xd4, 0x9e, 0x73, 0xbb, 0xca, 0x82, + 0xdb, 0x79, 0xc9, 0xda, 0xfc, 0x5f, 0x46, 0xfb, 0x55, 0x01, 0xea, 0x49, 0x49, 0x80, 0x89, 0xc9, + 0x1d, 0x89, 0x40, 0xb9, 0x63, 0x57, 0x44, 0x66, 0xe0, 0x1c, 0xc2, 0xee, 0x40, 0xc5, 0x56, 0x2a, + 0x4a, 0x8e, 0xfb, 0xb7, 0xf3, 0xf5, 0xc4, 0xd6, 0x2e, 0x4a, 0x7a, 0x81, 0x8a, 0x66, 0x5c, 0xb3, + 0x56, 0x3f, 0x06, 0xc8, 0x40, 0xb4, 0xf5, 0x54, 0xcc, 0x8c, 0x56, 0x6c, 0xb2, 0x6b, 0x50, 0x79, + 0x66, 0x7b, 0xd3, 0x24, 0x22, 0xf5, 0xc7, 0xbd, 0xe2, 0xc7, 0x05, 0xeb, 0x8f, 0x45, 0xa8, 0x99, + 0xfa, 0x82, 0xdd, 0x86, 0x1a, 0xd5, 0x17, 0xc6, 0xa2, 0xcb, 0xc3, 0x2f, 0xa1, 0xb0, 0xed, 0xb4, + 0x70, 0xca, 0xd9, 0x68, 0x54, 0xe9, 0x02, 0xca, 0xd8, 0x98, 0x95, 0x51, 0xa5, 0x91, 0x18, 0x9b, + 0x0a, 0xa9, 0x45, 0xf5, 0x88, 0x18, 0xbb, 0x81, 0x8b, 0xeb, 0xc3, 0x51, 0xc4, 0x6e, 0x27, 0xb3, + 0x2e, 0x93, 0xc6, 0xb7, 0xf2, 0x1a, 0x2f, 0x4e, 0xba, 0x0f, 0xcd, 0xdc, 0x30, 0x97, 0xcc, 0xfa, + 0xfd, 0xfc, 0xac, 0xcd, 0x90, 0xa4, 0x4e, 0x97, 0x77, 0xd9, 0x2a, 0xfc, 0x17, 0xeb, 0xf7, 0x11, + 0x40, 0xa6, 0xf2, 0xd5, 0x8f, 0x2f, 0xeb, 0x0f, 0x25, 0x80, 0x41, 0x88, 0x39, 0x70, 0x64, 0x53, + 0x7e, 0x5f, 0x76, 0x27, 0x81, 0x8c, 0xc4, 0x53, 0x0a, 0x73, 0xea, 0x5f, 0xe7, 0x4d, 0x8d, 0x51, + 0xc4, 0xb0, 0x5d, 0x68, 0x8e, 0x44, 0xec, 0x44, 0x2e, 0x39, 0x94, 0x59, 0xf4, 0x1b, 0x38, 0xa7, + 0x4c, 0xcf, 0x56, 0x37, 0x63, 0xe8, 0xb5, 0xca, 0xf7, 0x61, 0x3b, 0xb0, 0x2c, 0xce, 0x43, 0x19, + 0x29, 0x33, 0x8a, 0x2e, 0x43, 0xaf, 0xe8, 0x82, 0x16, 0x71, 0x1a, 0x89, 0x37, 0x45, 0xf6, 0xc1, + 0x6c, 0x28, 0x3b, 0x76, 0x18, 0x9b, 0xe4, 0xdf, 0x59, 0x18, 0x6f, 0xdf, 0x0e, 0xf5, 0xa2, 0xed, + 0x7d, 0x88, 0x73, 0xfd, 0xc5, 0x5f, 0x6f, 0xdc, 0xca, 0x55, 0x4c, 0xbe, 0x3c, 0x9e, 0x6d, 0x93, + 0xbf, 0x9c, 0xba, 0x6a, 0x7b, 0xaa, 0x5c, 0x6f, 0xdb, 0x0e, 0x5d, 0x54, 0x87, 0x1d, 0xfb, 0x5d, + 0x4e, 0xaa, 0xd9, 0xc7, 0xd0, 0x0a, 0x23, 0x39, 0x89, 0x44, 0x1c, 0x3f, 0xa5, 0xac, 0x68, 0xea, + 0xda, 0x37, 0x4c, 0xf6, 0x26, 0xc9, 0xa7, 0x28, 0xe0, 0x2b, 0x61, 0xfe, 0x73, 0xf5, 0x47, 0xd0, + 0x5e, 0x9c, 0xf1, 0xeb, 0xec, 0xde, 0xea, 0x5d, 0x68, 0xa4, 0x33, 0x78, 0x59, 0xc7, 0x7a, 0x7e, + 0xdb, 0x7f, 0x5f, 0x80, 0xaa, 0x8e, 0x47, 0x76, 0x17, 0x1a, 0x9e, 0x74, 0x6c, 0x34, 0x20, 0xb9, + 0x43, 0xbc, 0x93, 0x85, 0xeb, 0xd6, 0xe7, 0x89, 0x4c, 0xef, 0x47, 0xc6, 0x45, 0xf7, 0x74, 0x83, + 0xb1, 0x4c, 0xe2, 0xa7, 0x95, 0x75, 0xea, 0x07, 0x63, 0xc9, 0xb5, 0x70, 0xf5, 0x01, 0xb4, 0xe6, + 0x55, 0x5c, 0x62, 0xe7, 0x7b, 0xf3, 0x8e, 0x4e, 0xd9, 0x20, 0xed, 0x94, 0x37, 0xfb, 0x2e, 0x34, + 0x52, 0x9c, 0x6d, 0x5e, 0x34, 0x7c, 0x39, 0xdf, 0x33, 0x67, 0xab, 0xf5, 0xcb, 0x02, 0x40, 0x66, + 0x1b, 0x9e, 0x73, 0x78, 0x5b, 0x09, 0xb2, 0xea, 0x21, 0xfd, 0xa6, 0xe4, 0x6b, 0x2b, 0x9b, 0x6c, + 0x59, 0xe6, 0xd4, 0x66, 0x5b, 0x00, 0xa3, 0x34, 0xd6, 0x5f, 0x70, 0x02, 0xe4, 0x18, 0xa8, 0xdf, + 0xb3, 0x83, 0xc9, 0xd4, 0x9e, 0x08, 0x53, 0xe2, 0xa5, 0xdf, 0xd6, 0x00, 0xea, 0x89, 0x85, 0x6c, + 0x1d, 0x9a, 0xb1, 0xb1, 0x0a, 0x0b, 0x6e, 0x34, 0xa5, 0xc2, 0xf3, 0x10, 0x16, 0xce, 0x91, 0x1d, + 0x4c, 0xc4, 0x5c, 0xe1, 0xcc, 0x11, 0xe1, 0x46, 0x60, 0x7d, 0x01, 0x15, 0x02, 0x30, 0x7a, 0x63, + 0x65, 0x47, 0xca, 0xd4, 0xe0, 0xba, 0x78, 0x94, 0x31, 0x99, 0xb4, 0x57, 0x46, 0xff, 0xe6, 0x9a, + 0xc0, 0xde, 0xc7, 0x12, 0x75, 0x64, 0x96, 0xfb, 0x32, 0x1e, 0x8a, 0xad, 0x4f, 0xa0, 0x9e, 0xc0, + 0xb8, 0x2a, 0x9e, 0x1b, 0x08, 0x63, 0x22, 0xb5, 0xf1, 0xee, 0xe2, 0x9c, 0xd8, 0x91, 0xed, 0x28, + 0xa1, 0x6b, 0x98, 0x0a, 0xcf, 0x00, 0xeb, 0x3d, 0x68, 0xe6, 0x82, 0x12, 0x7d, 0xf1, 0x09, 0xed, + 0xb1, 0x3e, 0x1a, 0xf4, 0x87, 0xf5, 0x29, 0xac, 0xcc, 0x05, 0x08, 0x66, 0x32, 0x77, 0x94, 0x64, + 0x32, 0x9d, 0xa5, 0x2e, 0x94, 0x62, 0x0c, 0xca, 0x67, 0xc2, 0x3e, 0x35, 0x65, 0x18, 0xb5, 0xad, + 0xdf, 0xe1, 0x15, 0x2d, 0x29, 0x8f, 0xbf, 0x0f, 0x70, 0xa2, 0x54, 0xf8, 0x94, 0xea, 0x65, 0xa3, + 0xac, 0x81, 0x08, 0x31, 0xd8, 0x0d, 0x68, 0xe2, 0x47, 0x6c, 0xe4, 0x5a, 0x35, 0xf5, 0x88, 0x35, + 0xe1, 0x7b, 0xd0, 0x18, 0xa7, 0xdd, 0x4b, 0xc6, 0x3f, 0x92, 0xde, 0xef, 0x40, 0x3d, 0x90, 0x46, + 0xa6, 0xf7, 0xb6, 0x16, 0xc8, 0xb4, 0x9f, 0xed, 0x79, 0x46, 0x56, 0xd1, 0xfd, 0x6c, 0xcf, 0x23, + 0xa1, 0x75, 0x0b, 0xde, 0xb8, 0x70, 0xd9, 0x64, 0x6f, 0x41, 0x75, 0xec, 0x7a, 0x8a, 0x32, 0x16, + 0x5e, 0x17, 0xcc, 0x97, 0xf5, 0xaf, 0x02, 0x40, 0xe6, 0x5b, 0x18, 0x32, 0x98, 0x7a, 0x90, 0xb3, + 0xac, 0x53, 0x8d, 0x07, 0x75, 0xdf, 0x1c, 0x62, 0xc6, 0x33, 0xae, 0xcf, 0xfb, 0xe3, 0x56, 0x72, + 0xc6, 0xe9, 0xe3, 0x6d, 0xc7, 0x1c, 0x6f, 0xaf, 0x73, 0x21, 0x4c, 0x47, 0xa0, 0x2a, 0x2c, 0xff, + 0x3e, 0x00, 0x59, 0xac, 0x73, 0x23, 0x59, 0x7d, 0x00, 0x2b, 0x73, 0x43, 0xbe, 0x62, 0x42, 0xcb, + 0x0e, 0xe3, 0x7c, 0xa0, 0xef, 0x40, 0x55, 0x3f, 0x2c, 0xb0, 0x0d, 0xa8, 0xd9, 0x8e, 0x8e, 0xf1, + 0xdc, 0x39, 0x83, 0xc2, 0x5d, 0x82, 0x79, 0x22, 0xb6, 0xfe, 0x5c, 0x04, 0xc8, 0xf0, 0xd7, 0x28, + 0xc5, 0xef, 0x41, 0x2b, 0x16, 0x8e, 0x0c, 0x46, 0x76, 0x34, 0x23, 0xa9, 0xb9, 0xf9, 0x5e, 0xd6, + 0x65, 0x81, 0x99, 0x2b, 0xcb, 0x4b, 0x2f, 0x2f, 0xcb, 0x37, 0xa0, 0xec, 0xc8, 0x70, 0x66, 0xf2, + 0x16, 0x9b, 0x9f, 0xc8, 0xbe, 0x0c, 0x67, 0x07, 0x4b, 0x9c, 0x18, 0x6c, 0x0b, 0xaa, 0xfe, 0x29, + 0x3d, 0xb5, 0xe8, 0x8b, 0xe0, 0xb5, 0x79, 0xee, 0xc3, 0x53, 0x6c, 0x1f, 0x2c, 0x71, 0xc3, 0x62, + 0xb7, 0xa0, 0xe2, 0x9f, 0x8e, 0xdc, 0xc8, 0x64, 0x9e, 0xab, 0x8b, 0xf4, 0xae, 0x1b, 0xd1, 0xcb, + 0x0a, 0x72, 0x98, 0x05, 0xc5, 0xc8, 0x37, 0xef, 0x2a, 0xed, 0x85, 0xd5, 0xf4, 0x0f, 0x96, 0x78, + 0x31, 0xf2, 0xf7, 0xea, 0x50, 0xd5, 0xeb, 0x6a, 0xfd, 0xb3, 0x04, 0xad, 0x79, 0x2b, 0x71, 0x67, + 0xe3, 0xc8, 0x49, 0x76, 0x36, 0x8e, 0x9c, 0xf4, 0xc6, 0x52, 0xcc, 0xdd, 0x58, 0x2c, 0xa8, 0xc8, + 0xb3, 0x40, 0x44, 0xf9, 0x37, 0xa5, 0xfd, 0x13, 0x79, 0x16, 0x60, 0xd5, 0xac, 0x45, 0x73, 0x45, + 0x68, 0xc5, 0x14, 0xa1, 0xef, 0xc3, 0xca, 0x58, 0x7a, 0x9e, 0x3c, 0x1b, 0xce, 0x7c, 0xcf, 0x0d, + 0x4e, 0x4d, 0x25, 0x3a, 0x0f, 0xe2, 0x65, 0x7d, 0xe4, 0x46, 0x68, 0xce, 0xbe, 0x0c, 0x94, 0x08, + 0xe8, 0x1e, 0x8c, 0xbc, 0x45, 0x98, 0x7d, 0x06, 0xeb, 0xb6, 0x52, 0xc2, 0x0f, 0xd5, 0xe3, 0x20, + 0xb4, 0x9d, 0xd3, 0xae, 0x74, 0x28, 0x0a, 0xfd, 0xd0, 0x56, 0xee, 0xb1, 0xeb, 0xb9, 0x6a, 0x46, + 0x8b, 0x51, 0xe7, 0x2f, 0xe5, 0xb1, 0x0f, 0xa0, 0xe5, 0x44, 0xc2, 0x56, 0xa2, 0x2b, 0x62, 0x75, + 0x64, 0xab, 0x93, 0x4e, 0x9d, 0x7a, 0x2e, 0xa0, 0x38, 0x07, 0x1b, 0xad, 0xfd, 0xc2, 0xf5, 0x46, + 0x0e, 0xde, 0x3d, 0x1b, 0x7a, 0x0e, 0x73, 0x20, 0xdb, 0x02, 0x46, 0x40, 0xcf, 0x0f, 0xd5, 0x2c, + 0xa5, 0x02, 0x51, 0x2f, 0x91, 0xe0, 0x81, 0xab, 0x5c, 0x5f, 0xc4, 0xca, 0xf6, 0x43, 0xba, 0x56, + 0x97, 0x78, 0x06, 0xb0, 0x9b, 0xd0, 0x76, 0x03, 0xc7, 0x9b, 0x8e, 0xc4, 0xd3, 0x10, 0x27, 0x12, + 0x05, 0x71, 0x67, 0x99, 0x4e, 0x95, 0x2b, 0x06, 0x3f, 0x32, 0x30, 0x52, 0xc5, 0xf9, 0x02, 0x75, + 0x45, 0x53, 0x0d, 0x9e, 0x50, 0xad, 0x2f, 0x0b, 0xd0, 0x5e, 0x74, 0x3c, 0xdc, 0xb6, 0x10, 0x27, + 0x6f, 0x6e, 0xde, 0xd8, 0x4e, 0xb7, 0xb2, 0x98, 0xdb, 0xca, 0x24, 0x97, 0x96, 0x72, 0xb9, 0x34, + 0x75, 0x8b, 0xf2, 0x8b, 0xdd, 0x62, 0x6e, 0xa2, 0x95, 0x85, 0x89, 0x5a, 0xbf, 0x2d, 0xc0, 0x95, + 0x05, 0xe7, 0x7e, 0x65, 0x8b, 0xd6, 0xa1, 0xe9, 0xdb, 0xa7, 0x42, 0xbf, 0x5b, 0xc4, 0x26, 0x85, + 0xe4, 0xa1, 0xff, 0x81, 0x7d, 0x01, 0x2c, 0xe7, 0x23, 0xea, 0x52, 0xdb, 0x12, 0x07, 0x39, 0x94, + 0xea, 0xbe, 0x9c, 0x9a, 0x5c, 0x9c, 0x38, 0x48, 0x02, 0x5e, 0x74, 0xa3, 0xd2, 0x25, 0x6e, 0x64, + 0x1d, 0x42, 0x3d, 0x31, 0x90, 0xdd, 0x30, 0x0f, 0x4b, 0x85, 0xec, 0x65, 0xf5, 0x71, 0x2c, 0x22, + 0xb4, 0x5d, 0xbf, 0x32, 0xbd, 0x0b, 0x15, 0x5d, 0xa3, 0x16, 0x2f, 0x32, 0xb4, 0xc4, 0x1a, 0x42, + 0xcd, 0x20, 0x6c, 0x13, 0xaa, 0xc7, 0xb3, 0xf4, 0x91, 0xc5, 0x1c, 0x17, 0xf8, 0x3d, 0x32, 0x0c, + 0x3c, 0x83, 0x34, 0x83, 0x5d, 0x83, 0xf2, 0xf1, 0xac, 0xdf, 0xd5, 0xb7, 0x4e, 0x3c, 0xc9, 0xf0, + 0x6b, 0xaf, 0xaa, 0x0d, 0xb2, 0x3e, 0x87, 0xe5, 0x7c, 0xbf, 0x34, 0xb1, 0x17, 0x72, 0x89, 0x3d, + 0x3d, 0xb2, 0x8b, 0x2f, 0xbb, 0x7e, 0x7c, 0x04, 0x40, 0x0f, 0xc6, 0xaf, 0x7b, 0x6d, 0xf9, 0x21, + 0xd4, 0xcc, 0x43, 0x33, 0xfb, 0x60, 0xe1, 0xe1, 0xbc, 0x95, 0xbe, 0x42, 0xcf, 0xbd, 0x9e, 0x5b, + 0xf7, 0xb0, 0x80, 0x3d, 0x13, 0x51, 0xd7, 0x1d, 0x8f, 0x5f, 0x77, 0xb8, 0x7b, 0xd0, 0x7a, 0x1c, + 0x86, 0xff, 0x59, 0xdf, 0x9f, 0x42, 0x55, 0xbf, 0x77, 0x63, 0x1f, 0x0f, 0x2d, 0x30, 0x7b, 0xc0, + 0x74, 0x91, 0x9b, 0x37, 0x89, 0x6b, 0x02, 0x32, 0xa7, 0x38, 0x9e, 0xd9, 0x5c, 0x62, 0xce, 0x1b, + 0xc0, 0x35, 0x61, 0x73, 0x03, 0x6a, 0xe6, 0x69, 0x95, 0x35, 0xa0, 0xf2, 0xf8, 0x70, 0xd8, 0x7b, + 0xd4, 0x5e, 0x62, 0x75, 0x28, 0x1f, 0x0c, 0x86, 0x8f, 0xda, 0x05, 0x6c, 0x1d, 0x0e, 0x0e, 0x7b, + 0xed, 0xe2, 0xe6, 0x4d, 0x58, 0xce, 0x3f, 0xae, 0xb2, 0x26, 0xd4, 0x86, 0xbb, 0x87, 0xdd, 0xbd, + 0xc1, 0x4f, 0xda, 0x4b, 0x6c, 0x19, 0xea, 0xfd, 0xc3, 0x61, 0x6f, 0xff, 0x31, 0xef, 0xb5, 0x0b, + 0x9b, 0x3f, 0x86, 0x46, 0xfa, 0x8a, 0x84, 0x1a, 0xf6, 0xfa, 0x87, 0xdd, 0xf6, 0x12, 0x03, 0xa8, + 0x0e, 0x7b, 0xfb, 0xbc, 0x87, 0x7a, 0x6b, 0x50, 0x1a, 0x0e, 0x0f, 0xda, 0x45, 0x1c, 0x75, 0x7f, + 0x77, 0xff, 0xa0, 0xd7, 0x2e, 0x61, 0xf3, 0xd1, 0xc3, 0xa3, 0xfb, 0xc3, 0x76, 0x79, 0xf3, 0x23, + 0xb8, 0xb2, 0xf0, 0xbe, 0x42, 0xbd, 0x0f, 0x76, 0x79, 0x0f, 0x35, 0x35, 0xa1, 0x76, 0xc4, 0xfb, + 0x4f, 0x76, 0x1f, 0xf5, 0xda, 0x05, 0x14, 0x7c, 0x3e, 0xd8, 0x7f, 0xd0, 0xeb, 0xb6, 0x8b, 0x7b, + 0xd7, 0xbf, 0x7a, 0xbe, 0x56, 0xf8, 0xfa, 0xf9, 0x5a, 0xe1, 0x9b, 0xe7, 0x6b, 0x85, 0xbf, 0x3d, + 0x5f, 0x2b, 0x7c, 0xf9, 0xdd, 0xda, 0xd2, 0xd7, 0xdf, 0xad, 0x2d, 0x7d, 0xf3, 0xdd, 0xda, 0xd2, + 0x71, 0x95, 0xfe, 0x31, 0xf9, 0xf0, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x6a, 0xd0, 0x64, 0xbf, + 0x71, 0x19, 0x00, 0x00, } func (m *Op) Marshal() (dAtA []byte, err error) { @@ -3326,6 +3335,13 @@ func (m *ExecOp) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.NetworkConfigID) > 0 { + i -= len(m.NetworkConfigID) + copy(dAtA[i:], m.NetworkConfigID) + i = encodeVarintOps(dAtA, i, uint64(len(m.NetworkConfigID))) + i-- + dAtA[i] = 0x32 + } if len(m.Secretenv) > 0 { for iNdEx := len(m.Secretenv) - 1; iNdEx >= 0; iNdEx-- { { @@ -5704,6 +5720,10 @@ func (m *ExecOp) Size() (n int) { n += 1 + l + sovOps(uint64(l)) } } + l = len(m.NetworkConfigID) + if l > 0 { + n += 1 + l + sovOps(uint64(l)) + } return n } @@ -7471,6 +7491,38 @@ func (m *ExecOp) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NetworkConfigID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOps + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOps + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOps + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NetworkConfigID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipOps(dAtA[iNdEx:]) diff --git a/solver/pb/ops.proto b/solver/pb/ops.proto index 4788c093b7ae..e3c0c8895871 100644 --- a/solver/pb/ops.proto +++ b/solver/pb/ops.proto @@ -48,6 +48,7 @@ message ExecOp { NetMode network = 3; SecurityMode security = 4; repeated SecretEnv secretenv = 5; + string networkConfigID = 6; } // Meta is a set of arguments for ExecOp. diff --git a/source/git/cli.go b/source/git/cli.go new file mode 100644 index 000000000000..c2e6e45505ca --- /dev/null +++ b/source/git/cli.go @@ -0,0 +1,146 @@ +package git + +import ( + "bytes" + "context" + "io" + "os" + "os/exec" + "strings" + + "github.com/moby/buildkit/session/networks" + "github.com/moby/buildkit/util/progress/logs" + "github.com/pkg/errors" +) + +// gitCLI carries config to pass to the git CLI to make running multiple +// commands less repetitive. +// +// It may also contain references to config files that should be cleaned up +// when the CLI is done being used. +type gitCLI struct { + gitDir string // --git-dir flag + workTree string // --work-tree flag + sshAuthSock string // SSH_AUTH_SOCK env value + knownHosts string // file path passed to SSH + auth []string // extra auth flags passed to git + + hostsPath string // generated /etc/hosts from network config + resolvPath string // generated /etc/resolv.conf from network config +} + +// newGitCLI constructs a gitCLI and returns its cleanup function explicitly so +// it's harder to forget to call it. +func newGitCLI( + gitDir, + workDir, + sshAuthSock, + knownHosts string, + auth []string, + netConf *networks.Config, +) (*gitCLI, func(), error) { + cli := &gitCLI{ + gitDir: gitDir, + workTree: workDir, + sshAuthSock: sshAuthSock, + knownHosts: knownHosts, + auth: auth, + } + if err := cli.initConfig(netConf); err != nil { + cli.cleanup() + return nil, nil, err + } + return cli, cli.cleanup, nil +} + +func (cli *gitCLI) cleanup() { + if cli.hostsPath != "" { + os.Remove(cli.hostsPath) + } + if cli.resolvPath != "" { + os.Remove(cli.resolvPath) + } +} + +func (cli *gitCLI) withinDir(gitDir, workDir string) *gitCLI { + cp := *cli + cp.gitDir = gitDir + cp.workTree = workDir + return &cp +} + +func (cli *gitCLI) run(ctx context.Context, args ...string) (_ *bytes.Buffer, err error) { + for { + stdout, stderr, flush := logs.NewLogStreams(ctx, true) + defer stdout.Close() + defer stderr.Close() + defer func() { + if err != nil { + flush() + } + }() + if len(cli.auth) > 0 { + args = append(cli.auth, args...) + } + if cli.gitDir != "" { + args = append([]string{"--git-dir", cli.gitDir}, args...) + } + if cli.workTree != "" { + args = append([]string{"--work-tree", cli.workTree}, args...) + } + // Block sneaky repositories from using repos from the filesystem as submodules. + args = append([]string{"-c", "protocol.file.allow=user"}, args...) + cmd := exec.Command("git", args...) + cmd.Dir = cli.workTree // some commands like submodule require this + buf := bytes.NewBuffer(nil) + errbuf := bytes.NewBuffer(nil) + cmd.Stdin = nil + cmd.Stdout = io.MultiWriter(stdout, buf) + cmd.Stderr = io.MultiWriter(stderr, errbuf) + cmd.Env = []string{ + "PATH=" + os.Getenv("PATH"), + "GIT_TERMINAL_PROMPT=0", + "GIT_SSH_COMMAND=" + getGitSSHCommand(cli.knownHosts), + // "GIT_TRACE=1", + "GIT_CONFIG_NOSYSTEM=1", // Disable reading from system gitconfig. + "HOME=/dev/null", // Disable reading from user gitconfig. + "LC_ALL=C", // Ensure consistent output. + } + if cli.sshAuthSock != "" { + cmd.Env = append(cmd.Env, "SSH_AUTH_SOCK="+cli.sshAuthSock) + } + // remote git commands spawn helper processes that inherit FDs and don't + // handle parent death signal so exec.CommandContext can't be used + err := runWithStandardUmaskAndNetOverride(ctx, cmd, cli.hostsPath, cli.resolvPath) + if err != nil { + if strings.Contains(errbuf.String(), "--depth") || strings.Contains(errbuf.String(), "shallow") { + if newArgs := argsNoDepth(args); len(args) > len(newArgs) { + args = newArgs + continue + } + } + return buf, errors.Errorf("git error: %s\nstderr:\n%s", err, errbuf.String()) + } + return buf, nil + } +} + +func getGitSSHCommand(knownHosts string) string { + gitSSHCommand := "ssh -F /dev/null" + if knownHosts != "" { + gitSSHCommand += " -o UserKnownHostsFile=" + knownHosts + } else { + gitSSHCommand += " -o StrictHostKeyChecking=no" + } + return gitSSHCommand +} + +func argsNoDepth(args []string) []string { + out := make([]string, 0, len(args)) + for _, a := range args { + if a != "--depth=1" { + out = append(out, a) + } + } + return out +} diff --git a/source/git/gitsource.go b/source/git/gitsource.go index fdc1b50028db..8bef0ac87c8f 100644 --- a/source/git/gitsource.go +++ b/source/git/gitsource.go @@ -1,11 +1,9 @@ package git import ( - "bytes" "context" "encoding/base64" "fmt" - "io" "net/url" "os" "os/exec" @@ -20,6 +18,7 @@ import ( "github.com/moby/buildkit/client" "github.com/moby/buildkit/identity" "github.com/moby/buildkit/session" + "github.com/moby/buildkit/session/networks" "github.com/moby/buildkit/session/secrets" "github.com/moby/buildkit/session/sshforward" "github.com/moby/buildkit/snapshot" @@ -27,7 +26,6 @@ import ( "github.com/moby/buildkit/source" srctypes "github.com/moby/buildkit/source/types" "github.com/moby/buildkit/util/bklog" - "github.com/moby/buildkit/util/progress/logs" "github.com/moby/buildkit/util/urlutil" "github.com/moby/locker" "github.com/pkg/errors" @@ -40,11 +38,13 @@ var defaultBranch = regexp.MustCompile(`refs/heads/(\S+)`) type Opt struct { CacheAccessor cache.Accessor + DNSConfig *networks.DNSConfig } type gitSource struct { cache cache.Accessor locker *locker.Locker + dns *networks.DNSConfig } // Supported returns nil if the system supports Git source @@ -59,6 +59,7 @@ func NewSource(opt Opt) (source.Source, error) { gs := &gitSource{ cache: opt.CacheAccessor, locker: locker.New(), + dns: opt.DNSConfig, } return gs, nil } @@ -124,16 +125,22 @@ func (gs *gitSource) mountRemote(ctx context.Context, remote string, auth []stri } }() + git, cleanup, err := newGitCLI(dir, "", "", "", auth, nil) + if err != nil { + return "", nil, err + } + defer cleanup() + if initializeRepo { // Explicitly set the Git config 'init.defaultBranch' to the // implied default to suppress "hint:" output about not having a // default initial branch name set which otherwise spams unit // test logs. - if _, err := gitWithinDir(ctx, dir, "", "", "", auth, "-c", "init.defaultBranch=master", "init", "--bare"); err != nil { + if _, err := git.run(ctx, "-c", "init.defaultBranch=master", "init", "--bare"); err != nil { return "", nil, errors.Wrapf(err, "failed to init repo at %s", dir) } - if _, err := gitWithinDir(ctx, dir, "", "", "", auth, "remote", "add", "origin", remote); err != nil { + if _, err := git.run(ctx, "remote", "add", "origin", remote); err != nil { return "", nil, errors.Wrapf(err, "failed add origin repo at %s", dir) } @@ -296,6 +303,24 @@ func (gs *gitSourceHandler) mountKnownHosts(ctx context.Context) (string, func() return knownHosts.Name(), cleanup, nil } +func (gs *gitSourceHandler) networkConfig(ctx context.Context, g session.Group) (*networks.Config, error) { + // base network config inherits from system-wide config + netConfig := networks.FromDNSConfig(gs.dns) + + if gs.src.NetworkConfigID != "" { + err := gs.sm.Any(ctx, g, func(ctx context.Context, _ string, caller session.Caller) error { + var err error + netConfig, err = networks.MergeConfig(ctx, caller, netConfig, gs.src.NetworkConfigID) + return err + }) + if err != nil { + return nil, err + } + } + + return netConfig, nil +} + func (gs *gitSourceHandler) CacheKey(ctx context.Context, g session.Group, index int) (string, string, solver.CacheOpts, bool, error) { remote := gs.src.Remote gs.locker.Lock(remote) @@ -335,9 +360,20 @@ func (gs *gitSourceHandler) CacheKey(ctx context.Context, g session.Group, index defer unmountKnownHosts() } + netConf, err := gs.networkConfig(ctx, g) + if err != nil { + return "", "", nil, false, err + } + + git, cleanup, err := newGitCLI(gitDir, "", sock, knownHosts, gs.auth, netConf) + if err != nil { + return "", "", nil, false, err + } + defer cleanup() + ref := gs.src.Ref if ref == "" { - ref, err = getDefaultBranch(ctx, gitDir, "", sock, knownHosts, gs.auth, gs.src.Remote) + ref, err = getDefaultBranch(ctx, git, gs.src.Remote) if err != nil { return "", "", nil, false, err } @@ -345,7 +381,7 @@ func (gs *gitSourceHandler) CacheKey(ctx context.Context, g session.Group, index // TODO: should we assume that remote tag is immutable? add a timer? - buf, err := gitWithinDir(ctx, gitDir, "", sock, knownHosts, gs.auth, "ls-remote", "origin", ref) + buf, err := git.run(ctx, "ls-remote", "origin", ref) if err != nil { return "", "", nil, false, errors.Wrapf(err, "failed to fetch remote %s", urlutil.RedactCredentials(remote)) } @@ -416,9 +452,20 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out defer unmountKnownHosts() } + netConf, err := gs.networkConfig(ctx, g) + if err != nil { + return nil, err + } + + git, cleanup, err := newGitCLI(gitDir, "", sock, knownHosts, gs.auth, netConf) + if err != nil { + return nil, err + } + defer cleanup() + ref := gs.src.Ref if ref == "" { - ref, err = getDefaultBranch(ctx, gitDir, "", sock, knownHosts, gs.auth, gs.src.Remote) + ref, err = getDefaultBranch(ctx, git, gs.src.Remote) if err != nil { return nil, err } @@ -427,7 +474,7 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out doFetch := true if isCommitSHA(ref) { // skip fetch if commit already exists - if _, err := gitWithinDir(ctx, gitDir, "", sock, knownHosts, nil, "cat-file", "-e", ref+"^{commit}"); err == nil { + if _, err := git.run(ctx, "cat-file", "-e", ref+"^{commit}"); err == nil { doFetch = false } } @@ -451,10 +498,10 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out // in case the ref is a branch and it now points to a different commit sha // TODO: is there a better way to do this? } - if _, err := gitWithinDir(ctx, gitDir, "", sock, knownHosts, gs.auth, args...); err != nil { + if _, err := git.run(ctx, args...); err != nil { return nil, errors.Wrapf(err, "failed to fetch remote %s", urlutil.RedactCredentials(gs.src.Remote)) } - _, err = gitWithinDir(ctx, gitDir, "", sock, knownHosts, nil, "reflog", "expire", "--all", "--expire=now") + _, err = git.run(ctx, "reflog", "expire", "--all", "--expire=now") if err != nil { return nil, errors.Wrapf(err, "failed to expire reflog for remote %s", urlutil.RedactCredentials(gs.src.Remote)) } @@ -496,19 +543,20 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out if err := os.MkdirAll(checkoutDir, 0711); err != nil { return nil, err } - _, err = gitWithinDir(ctx, checkoutDirGit, "", sock, knownHosts, nil, "-c", "init.defaultBranch=master", "init") + checkoutGit := git.withinDir(checkoutDirGit, checkoutDir) + _, err = checkoutGit.run(ctx, "-c", "init.defaultBranch=master", "init") if err != nil { return nil, err } // Defense-in-depth: clone using the file protocol to disable local-clone // optimizations which can be abused on some versions of Git to copy unintended // host files into the build context. - _, err = gitWithinDir(ctx, checkoutDirGit, "", sock, knownHosts, nil, "remote", "add", "origin", "file://"+gitDir) + _, err = checkoutGit.run(ctx, "remote", "add", "origin", "file://"+gitDir) if err != nil { return nil, err } - gitCatFileBuf, err := gitWithinDir(ctx, gitDir, "", sock, knownHosts, gs.auth, "cat-file", "-t", ref) + gitCatFileBuf, err := git.run(ctx, "cat-file", "-t", ref) if err != nil { return nil, err } @@ -519,26 +567,26 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out pullref += ":refs/tags/" + pullref } else if isCommitSHA(ref) { pullref = "refs/buildkit/" + identity.NewID() - _, err = gitWithinDir(ctx, gitDir, "", sock, knownHosts, gs.auth, "update-ref", pullref, ref) + _, err = git.run(ctx, "update-ref", pullref, ref) if err != nil { return nil, err } } else { pullref += ":" + pullref } - _, err = gitWithinDir(ctx, checkoutDirGit, "", sock, knownHosts, gs.auth, "fetch", "-u", "--depth=1", "origin", pullref) + _, err = checkoutGit.run(ctx, "fetch", "-u", "--depth=1", "origin", pullref) if err != nil { return nil, err } - _, err = gitWithinDir(ctx, checkoutDirGit, checkoutDir, sock, knownHosts, nil, "checkout", "FETCH_HEAD") + _, err = checkoutGit.run(ctx, "checkout", "FETCH_HEAD") if err != nil { return nil, errors.Wrapf(err, "failed to checkout remote %s", urlutil.RedactCredentials(gs.src.Remote)) } - _, err = gitWithinDir(ctx, checkoutDirGit, "", sock, knownHosts, nil, "remote", "set-url", "origin", urlutil.RedactCredentials(gs.src.Remote)) + _, err = checkoutGit.run(ctx, "remote", "set-url", "origin", urlutil.RedactCredentials(gs.src.Remote)) if err != nil { return nil, errors.Wrapf(err, "failed to set remote origin to %s", urlutil.RedactCredentials(gs.src.Remote)) } - _, err = gitWithinDir(ctx, checkoutDirGit, "", sock, knownHosts, nil, "reflog", "expire", "--all", "--expire=now") + _, err = checkoutGit.run(ctx, "reflog", "expire", "--all", "--expire=now") if err != nil { return nil, errors.Wrapf(err, "failed to expire reflog for remote %s", urlutil.RedactCredentials(gs.src.Remote)) } @@ -554,7 +602,7 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out return nil, errors.Wrapf(err, "failed to create temporary checkout dir") } } - _, err = gitWithinDir(ctx, gitDir, cd, sock, knownHosts, nil, "checkout", ref, "--", ".") + _, err = git.withinDir(gitDir, cd).run(ctx, "checkout", ref, "--", ".") if err != nil { return nil, errors.Wrapf(err, "failed to checkout remote %s", urlutil.RedactCredentials(gs.src.Remote)) } @@ -587,7 +635,7 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out } } - _, err = gitWithinDir(ctx, gitDir, checkoutDir, sock, knownHosts, gs.auth, "submodule", "update", "--init", "--recursive", "--depth=1") + _, err = git.withinDir(gitDir, checkoutDir).run(ctx, "submodule", "update", "--init", "--recursive", "--depth=1") if err != nil { return nil, errors.Wrapf(err, "failed to update submodules for %s", urlutil.RedactCredentials(gs.src.Remote)) } @@ -628,79 +676,6 @@ func isCommitSHA(str string) bool { return validHex.MatchString(str) } -func gitWithinDir(ctx context.Context, gitDir, workDir, sshAuthSock, knownHosts string, auth []string, args ...string) (*bytes.Buffer, error) { - a := append([]string{"--git-dir", gitDir}, auth...) - if workDir != "" { - a = append(a, "--work-tree", workDir) - } - return git(ctx, workDir, sshAuthSock, knownHosts, append(a, args...)...) -} - -func getGitSSHCommand(knownHosts string) string { - gitSSHCommand := "ssh -F /dev/null" - if knownHosts != "" { - gitSSHCommand += " -o UserKnownHostsFile=" + knownHosts - } else { - gitSSHCommand += " -o StrictHostKeyChecking=no" - } - return gitSSHCommand -} - -func git(ctx context.Context, dir, sshAuthSock, knownHosts string, args ...string) (_ *bytes.Buffer, err error) { - for { - stdout, stderr, flush := logs.NewLogStreams(ctx, false) - defer stdout.Close() - defer stderr.Close() - defer func() { - if err != nil { - flush() - } - }() - args = append([]string{"-c", "protocol.file.allow=user"}, args...) // Block sneaky repositories from using repos from the filesystem as submodules. - cmd := exec.Command("git", args...) - cmd.Dir = dir // some commands like submodule require this - buf := bytes.NewBuffer(nil) - errbuf := bytes.NewBuffer(nil) - cmd.Stdin = nil - cmd.Stdout = io.MultiWriter(stdout, buf) - cmd.Stderr = io.MultiWriter(stderr, errbuf) - cmd.Env = []string{ - "PATH=" + os.Getenv("PATH"), - "GIT_TERMINAL_PROMPT=0", - "GIT_SSH_COMMAND=" + getGitSSHCommand(knownHosts), - // "GIT_TRACE=1", - "GIT_CONFIG_NOSYSTEM=1", // Disable reading from system gitconfig. - "HOME=/dev/null", // Disable reading from user gitconfig. - "LC_ALL=C", // Ensure consistent output. - } - if sshAuthSock != "" { - cmd.Env = append(cmd.Env, "SSH_AUTH_SOCK="+sshAuthSock) - } - // remote git commands spawn helper processes that inherit FDs and don't - // handle parent death signal so exec.CommandContext can't be used - err := runWithStandardUmask(ctx, cmd) - if err != nil { - if strings.Contains(errbuf.String(), "--depth") || strings.Contains(errbuf.String(), "shallow") { - if newArgs := argsNoDepth(args); len(args) > len(newArgs) { - args = newArgs - continue - } - } - } - return buf, err - } -} - -func argsNoDepth(args []string) []string { - out := make([]string, 0, len(args)) - for _, a := range args { - if a != "--depth=1" { - out = append(out, a) - } - } - return out -} - func tokenScope(remote string) string { // generally we can only use the token for fetching main remote but in case of github.com we do best effort // to try reuse same token for all github.com remotes. This is the same behavior actions/checkout uses @@ -713,8 +688,8 @@ func tokenScope(remote string) string { } // getDefaultBranch gets the default branch of a repository using ls-remote -func getDefaultBranch(ctx context.Context, gitDir, workDir, sshAuthSock, knownHosts string, auth []string, remoteURL string) (string, error) { - buf, err := gitWithinDir(ctx, gitDir, workDir, sshAuthSock, knownHosts, auth, "ls-remote", "--symref", remoteURL, "HEAD") +func getDefaultBranch(ctx context.Context, git *gitCLI, remoteURL string) (string, error) { + buf, err := git.run(ctx, "ls-remote", "--symref", remoteURL, "HEAD") if err != nil { return "", errors.Wrapf(err, "error fetching default branch for repository %s", urlutil.RedactCredentials(remoteURL)) } diff --git a/source/git/gitsource_test.go b/source/git/gitsource_test.go index 28b2a54bb51f..b3a364e13739 100644 --- a/source/git/gitsource_test.go +++ b/source/git/gitsource_test.go @@ -285,13 +285,17 @@ func testFetchByTag(t *testing.T, tag, expectedCommitSubject string, isAnnotated } if keepGitDir { + git, cleanup, err := newGitCLI("", dir, "", "", nil, nil) + require.NoError(t, err) + defer cleanup() + if isAnnotatedTag { // get commit sha that the annotated tag points to - annotatedTagCommit, err := git(ctx, dir, "", "", "rev-list", "-n", "1", tag) + annotatedTagCommit, err := git.run(ctx, "rev-list", "-n", "1", tag) require.NoError(t, err) // get current commit sha - headCommit, err := git(ctx, dir, "", "", "rev-parse", "HEAD") + headCommit, err := git.run(ctx, "rev-parse", "HEAD") require.NoError(t, err) // HEAD should match the actual commit sha (and not the sha of the annotated tag, @@ -302,9 +306,9 @@ func testFetchByTag(t *testing.T, tag, expectedCommitSubject string, isAnnotated // test that we checked out the correct commit // (in the case of an annotated tag, this message is of the commit the annotated tag points to // and not the message of the tag) - gitLogOutput, err := git(ctx, dir, "", "", "log", "-n", "1", "--format=%s") + gitLogOutput, err := git.run(ctx, "log", "-n", "1", "--format=%s") require.NoError(t, err) - require.True(t, strings.Contains(strings.TrimSpace(gitLogOutput.String()), expectedCommitSubject)) + require.Contains(t, strings.TrimSpace(gitLogOutput.String()), expectedCommitSubject) } } @@ -578,7 +582,7 @@ func setupGitRepo(t *testing.T) gitRepoFixture { "echo sbb > foo13", "git add foo13", "git commit -m third", - "git tag lightweight-tag", + "git tag --no-sign lightweight-tag", "git checkout -B feature", "echo baz > ghi", "git add ghi", diff --git a/source/git/gitsource_unix.go b/source/git/gitsource_unix.go index 142ae5609140..89f57060a9a1 100644 --- a/source/git/gitsource_unix.go +++ b/source/git/gitsource_unix.go @@ -4,23 +4,31 @@ package git import ( + "bufio" "context" + "fmt" + "io" + "os" "os/exec" "runtime" + "strings" "syscall" "time" + "github.com/moby/buildkit/session/networks" + "github.com/moby/sys/mount" + "github.com/pkg/errors" "golang.org/x/sys/unix" ) -func runWithStandardUmask(ctx context.Context, cmd *exec.Cmd) error { +func runWithStandardUmaskAndNetOverride(ctx context.Context, cmd *exec.Cmd, hosts, resolv string) error { errCh := make(chan error) go func() { defer close(errCh) runtime.LockOSThread() - if err := unshareAndRun(ctx, cmd); err != nil { + if err := unshareAndRun(ctx, cmd, hosts, resolv); err != nil { errCh <- err } }() @@ -29,11 +37,14 @@ func runWithStandardUmask(ctx context.Context, cmd *exec.Cmd) error { } // unshareAndRun needs to be called in a locked thread. -func unshareAndRun(ctx context.Context, cmd *exec.Cmd) error { - if err := syscall.Unshare(syscall.CLONE_FS); err != nil { +func unshareAndRun(ctx context.Context, cmd *exec.Cmd, hosts, resolv string) error { + if err := syscall.Unshare(syscall.CLONE_FS | syscall.CLONE_NEWNS); err != nil { return err } syscall.Umask(0022) + if err := overrideNetworkConfig(hosts, resolv); err != nil { + return errors.Wrapf(err, "failed to override network config") + } return runProcessGroup(ctx, cmd) } @@ -64,3 +75,152 @@ func runProcessGroup(ctx context.Context, cmd *exec.Cmd) error { close(waitDone) return err } + +func overrideNetworkConfig(hostsOverride, resolvOverride string) error { + if hostsOverride != "" { + if err := mount.Mount(hostsOverride, "/etc/hosts", "", "bind"); err != nil { + return errors.Wrap(err, "mount hosts override") + } + } + + if resolvOverride != "" { + if err := syscall.Mount(resolvOverride, "/etc/resolv.conf", "", syscall.MS_BIND, ""); err != nil { + return errors.Wrap(err, "mount resolv override") + } + } + + return nil +} + +func (s *gitCLI) initConfig(netConf *networks.Config) error { + if netConf == nil { + return nil + } + + if len(netConf.IpHosts) > 0 { + if err := s.generateHosts(netConf.IpHosts); err != nil { + return err + } + } + + if netConf.Dns != nil { + if err := s.generateResolv(netConf.Dns); err != nil { + return err + } + } + + return nil +} + +func (s *gitCLI) generateHosts(extraHosts []*networks.IPHosts) error { + src, err := os.Open("/etc/hosts") + if err != nil { + return errors.Wrap(err, "read current hosts") + } + defer src.Close() + + override, err := os.CreateTemp("", "buildkit-git-extra-hosts") + if err != nil { + return errors.Wrap(err, "create hosts override") + } + defer override.Close() + + s.hostsPath = override.Name() + + if err := mergeHosts(override, src, extraHosts); err != nil { + return err + } + + return override.Close() +} + +func (s *gitCLI) generateResolv(dns *networks.DNSConfig) error { + src, err := os.Open("/etc/resolv.conf") + if err != nil { + return err + } + defer src.Close() + + override, err := os.CreateTemp("", "buildkit-git-resolv") + if err != nil { + return errors.Wrap(err, "create hosts override") + } + + s.resolvPath = override.Name() + + defer override.Close() + + if err := mergeResolv(override, src, dns); err != nil { + return err + } + + return nil +} + +func mergeHosts(override *os.File, currentHosts io.Reader, extraHosts []*networks.IPHosts) error { + if _, err := io.Copy(override, currentHosts); err != nil { + return errors.Wrap(err, "write current hosts") + } + + if _, err := fmt.Fprintln(override); err != nil { + return errors.Wrap(err, "write newline") + } + + for _, host := range extraHosts { + hosts := strings.Join(host.Hosts, " ") + if _, err := fmt.Fprintf(override, "%s\t%s\n", host.Ip, hosts); err != nil { + return errors.Wrap(err, "write extra host") + } + } + + if err := override.Close(); err != nil { + return errors.Wrap(err, "close hosts override") + } + + return nil +} + +func mergeResolv(dst *os.File, src io.Reader, dns *networks.DNSConfig) error { + srcScan := bufio.NewScanner(src) + + var replacedSearch bool + var replacedOptions bool + + for _, ns := range dns.Nameservers { + fmt.Fprintln(dst, "nameserver", ns) + } + + for srcScan.Scan() { + switch { + case strings.HasPrefix(srcScan.Text(), "search"): + oldDomains := strings.Fields(srcScan.Text())[1:] + newDomains := append([]string{}, dns.SearchDomains...) + newDomains = append(newDomains, oldDomains...) + fmt.Fprintln(dst, "search", strings.Join(newDomains, " ")) + replacedSearch = true + case strings.HasPrefix(srcScan.Text(), "options"): + oldOptions := strings.Fields(srcScan.Text())[1:] + newOptions := append([]string{}, dns.Options...) + newOptions = append(newOptions, oldOptions...) + fmt.Fprintln(dst, "options", strings.Join(newOptions, " ")) + replacedOptions = true + case strings.HasPrefix(srcScan.Text(), "nameserver"): + if len(dns.Nameservers) == 0 { + // preserve existing nameservers + fmt.Fprintln(dst, srcScan.Text()) + } + default: + fmt.Fprintln(dst, srcScan.Text()) + } + } + + if !replacedSearch { + fmt.Fprintln(dst, "search", strings.Join(dns.SearchDomains, " ")) + } + + if !replacedOptions { + fmt.Fprintln(dst, "options", strings.Join(dns.Options, " ")) + } + + return nil +} diff --git a/source/git/gitsource_windows.go b/source/git/gitsource_windows.go index 8c8a1d3dcf26..f342fe33b258 100644 --- a/source/git/gitsource_windows.go +++ b/source/git/gitsource_windows.go @@ -5,10 +5,13 @@ package git import ( "context" + "errors" "os/exec" + + "github.com/moby/buildkit/session/networks" ) -func runWithStandardUmask(ctx context.Context, cmd *exec.Cmd) error { +func runWithStandardUmaskAndNetOverride(ctx context.Context, cmd *exec.Cmd, hosts, resolv string) error { if err := cmd.Start(); err != nil { return err } @@ -22,3 +25,11 @@ func runWithStandardUmask(ctx context.Context, cmd *exec.Cmd) error { }() return cmd.Wait() } + +func (s *gitCLI) initConfig(netConf *networks.Config) error { + if netConf == nil { + return nil + } + + return errors.New("overriding network config is not supported on Windows") +} diff --git a/source/gitidentifier.go b/source/gitidentifier.go index 6055c94e2f9b..b39bf44f90cd 100644 --- a/source/gitidentifier.go +++ b/source/gitidentifier.go @@ -18,6 +18,7 @@ type GitIdentifier struct { AuthHeaderSecret string MountSSHSock string KnownSSHHosts string + NetworkConfigID string } func NewGitIdentifier(remoteURL string) (*GitIdentifier, error) { diff --git a/source/http/httpsource.go b/source/http/httpsource.go index 9fde3cdee7ad..10548c89b8e0 100644 --- a/source/http/httpsource.go +++ b/source/http/httpsource.go @@ -18,6 +18,7 @@ import ( "github.com/docker/docker/pkg/idtools" "github.com/moby/buildkit/cache" "github.com/moby/buildkit/session" + "github.com/moby/buildkit/session/networks" "github.com/moby/buildkit/snapshot" "github.com/moby/buildkit/solver" "github.com/moby/buildkit/source" @@ -31,12 +32,14 @@ import ( type Opt struct { CacheAccessor cache.Accessor Transport http.RoundTripper + DNSConfig *networks.DNSConfig } type httpSource struct { cache cache.Accessor locker *locker.Locker transport http.RoundTripper + dns *networks.DNSConfig } func NewSource(opt Opt) (source.Source, error) { @@ -48,6 +51,7 @@ func NewSource(opt Opt) (source.Source, error) { cache: opt.CacheAccessor, locker: locker.New(), transport: transport, + dns: opt.DNSConfig, } return hs, nil } @@ -77,8 +81,22 @@ func (hs *httpSource) Resolve(ctx context.Context, id source.Identifier, sm *ses }, nil } -func (hs *httpSourceHandler) client(g session.Group) *http.Client { - return &http.Client{Transport: newTransport(hs.transport, hs.sm, g)} +func (hs *httpSourceHandler) client(ctx context.Context, g session.Group) (*http.Client, error) { + // base network config inherits from system-wide config + netConfig := networks.FromDNSConfig(hs.dns) + + if hs.src.NetworkConfigID != "" { + err := hs.sm.Any(ctx, g, func(ctx context.Context, _ string, caller session.Caller) error { + var err error + netConfig, err = networks.MergeConfig(ctx, caller, netConfig, hs.src.NetworkConfigID) + return err + }) + if err != nil { + return nil, err + } + } + + return &http.Client{Transport: newTransport(hs.transport, hs.sm, g, netConfig)}, nil } // urlHash is internal hash the etag is stored by that doesn't leak outside @@ -171,7 +189,10 @@ func (hs *httpSourceHandler) CacheKey(ctx context.Context, g session.Group, inde } } - client := hs.client(g) + client, err := hs.client(ctx, g) + if err != nil { + return "", "", nil, false, err + } // Some servers seem to have trouble supporting If-None-Match properly even // though they return ETag-s. So first, optionally try a HEAD request with @@ -393,7 +414,10 @@ func (hs *httpSourceHandler) Snapshot(ctx context.Context, g session.Group) (cac } req = req.WithContext(ctx) - client := hs.client(g) + client, err := hs.client(ctx, g) + if err != nil { + return nil, err + } resp, err := client.Do(req) if err != nil { diff --git a/source/http/transport.go b/source/http/transport.go index e511e8634fb6..10c3b4ee7abf 100644 --- a/source/http/transport.go +++ b/source/http/transport.go @@ -6,25 +6,36 @@ import ( "net/http" "github.com/moby/buildkit/session" + "github.com/moby/buildkit/session/networks" "github.com/moby/buildkit/session/upload" + "github.com/moby/buildkit/source/netconfhttp" "github.com/pkg/errors" ) -func newTransport(rt http.RoundTripper, sm *session.Manager, g session.Group) http.RoundTripper { - return &sessionHandler{rt: rt, sm: sm, g: g} +func newTransport(rt http.RoundTripper, sm *session.Manager, g session.Group, netConfig *networks.Config) http.RoundTripper { + return &sessionHandler{ + rt: netconfhttp.NewTransport(rt, netConfig), + sm: sm, + g: g, + } } type sessionHandler struct { - sm *session.Manager rt http.RoundTripper + + sm *session.Manager g session.Group } func (h *sessionHandler) RoundTrip(req *http.Request) (*http.Response, error) { - if req.URL.Host != "buildkit-session" { - return h.rt.RoundTrip(req) + if req.URL.Host == "buildkit-session" { + return h.handleSession(req) } + return h.rt.RoundTrip(req) +} + +func (h *sessionHandler) handleSession(req *http.Request) (*http.Response, error) { if req.Method != "GET" { return nil, errors.Errorf("invalid request") } diff --git a/source/identifier.go b/source/identifier.go index aad9f226ff6e..411511c6ac41 100644 --- a/source/identifier.go +++ b/source/identifier.go @@ -119,6 +119,8 @@ func FromLLB(op *pb.Op_Source, platform *pb.Platform) (Identifier, error) { id.KnownSSHHosts = v case pb.AttrMountSSHSock: id.MountSSHSock = v + case pb.AttrNetworkConfigID: + id.NetworkConfigID = v } } } @@ -190,6 +192,8 @@ func FromLLB(op *pb.Op_Source, platform *pb.Platform) (Identifier, error) { return nil, err } id.GID = int(i) + case pb.AttrNetworkConfigID: + id.NetworkConfigID = v } } } @@ -275,13 +279,14 @@ func NewHTTPIdentifier(str string, tls bool) (*HTTPIdentifier, error) { } type HTTPIdentifier struct { - TLS bool - URL string - Checksum digest.Digest - Filename string - Perm int - UID int - GID int + TLS bool + URL string + Checksum digest.Digest + Filename string + Perm int + UID int + GID int + NetworkConfigID string } func (*HTTPIdentifier) ID() string { diff --git a/source/netconfhttp/transport.go b/source/netconfhttp/transport.go new file mode 100644 index 000000000000..69fe79064bd4 --- /dev/null +++ b/source/netconfhttp/transport.go @@ -0,0 +1,131 @@ +package netconfhttp + +import ( + "context" + "net" + "net/http" + "strings" + + "github.com/hashicorp/go-multierror" + "github.com/moby/buildkit/session/networks" + "github.com/pkg/errors" +) + +// NewTransport returns a http.RoundTripper that will respect the settings in +// the given network configuration as a logical override to the host's +// /etc/hosts and/or /etc/resolv.conf. +func NewTransport(rt http.RoundTripper, netConfig *networks.Config) http.RoundTripper { + hostsMap := map[string]string{} + for _, ipHosts := range netConfig.IpHosts { + for _, host := range ipHosts.Hosts { + hostsMap[host] = ipHosts.Ip + } + } + + var domains []string + var resolver *net.Resolver + if netConfig.Dns == nil { + resolver = net.DefaultResolver + } else { + domains = netConfig.Dns.SearchDomains + + dialer := net.Dialer{} + resolver = &net.Resolver{ + PreferGo: true, + Dial: func(ctx context.Context, network, address string) (net.Conn, error) { + var errs error + for _, ns := range netConfig.Dns.Nameservers { + conn, err := dialer.DialContext(ctx, network, net.JoinHostPort(ns, "53")) + if err != nil { + errs = multierror.Append(errs, err) + continue + } + + return conn, nil + } + + return nil, errs + }, + } + } + + return &transport{ + rt: rt, + resolver: resolver, + hosts: hostsMap, + searchDomains: domains, + } +} + +type transport struct { + rt http.RoundTripper + + resolver *net.Resolver + hosts map[string]string + searchDomains []string +} + +func (h *transport) RoundTrip(req *http.Request) (*http.Response, error) { + var remapped bool + if len(h.hosts) > 0 { + if host, port, err := net.SplitHostPort(req.URL.Host); err == nil { + remap, found := h.hosts[host] + if found { + req.URL.Host = net.JoinHostPort(remap, port) + remapped = true + } + } else { + remap, found := h.hosts[req.URL.Host] + if found { + req.URL.Host = remap + remapped = true + } + } + } + + if !remapped && strings.Count(req.URL.Host, ".") == 0 && len(h.searchDomains) > 0 { + if host, port, err := net.SplitHostPort(req.URL.Host); err == nil { + ip, err := h.lookup(req.Context(), host) + if err != nil { + return nil, err + } + + req.URL.Host = net.JoinHostPort(ip.String(), port) + } else { + ip, err := h.lookup(req.Context(), req.URL.Host) + if err != nil { + return nil, err + } + + req.URL.Host = ip.String() + } + } + + return h.rt.RoundTrip(req) +} + +func (h *transport) lookup(ctx context.Context, target string) (net.IP, error) { + var errs error + for _, domain := range append([]string{""}, h.searchDomains...) { + qualified := target + + if domain != "" { + qualified += "." + domain + } + + ips, err := h.resolver.LookupIPAddr(ctx, qualified) + if err != nil { + errs = multierror.Append(errs, err) + continue + } + + if len(ips) > 0 { + return ips[0].IP, nil + } + } + if errs != nil { + return nil, errs + } + + return nil, errors.Errorf("no IPs found for %s", target) +} diff --git a/worker/base/worker.go b/worker/base/worker.go index 8d402ff2fb1b..b3eb4d5d0e68 100644 --- a/worker/base/worker.go +++ b/worker/base/worker.go @@ -29,6 +29,7 @@ import ( "github.com/moby/buildkit/frontend" "github.com/moby/buildkit/identity" "github.com/moby/buildkit/session" + "github.com/moby/buildkit/session/networks" "github.com/moby/buildkit/snapshot" containerdsnapshot "github.com/moby/buildkit/snapshot/containerd" "github.com/moby/buildkit/snapshot/imagerefchecker" @@ -67,6 +68,7 @@ type WorkerOpt struct { GCPolicy []client.PruneInfo BuildkitVersion client.BuildkitVersion NetworkProviders map[pb.NetMode]network.Provider + DNSConfig *networks.DNSConfig Executor executor.Executor Snapshotter snapshot.Snapshotter ContentStore *containerdsnapshot.Store @@ -140,6 +142,7 @@ func NewWorker(ctx context.Context, opt WorkerOpt) (*Worker, error) { if err := git.Supported(); err == nil { gs, err := git.NewSource(git.Opt{ CacheAccessor: cm, + DNSConfig: opt.DNSConfig, }) if err != nil { return nil, err @@ -151,6 +154,7 @@ func NewWorker(ctx context.Context, opt WorkerOpt) (*Worker, error) { hs, err := http.NewSource(http.Opt{ CacheAccessor: cm, + DNSConfig: opt.DNSConfig, }) if err != nil { return nil, err diff --git a/worker/containerd/containerd.go b/worker/containerd/containerd.go index e8d948d0e8c6..f9b1235288de 100644 --- a/worker/containerd/containerd.go +++ b/worker/containerd/containerd.go @@ -14,7 +14,7 @@ import ( "github.com/moby/buildkit/cache" "github.com/moby/buildkit/cache/metadata" "github.com/moby/buildkit/executor/containerdexecutor" - "github.com/moby/buildkit/executor/oci" + "github.com/moby/buildkit/session/networks" containerdsnapshot "github.com/moby/buildkit/snapshot/containerd" "github.com/moby/buildkit/util/leaseutil" "github.com/moby/buildkit/util/network/netproviders" @@ -27,7 +27,7 @@ import ( ) // NewWorkerOpt creates a WorkerOpt. -func NewWorkerOpt(root string, address, snapshotterName, ns string, rootless bool, labels map[string]string, dns *oci.DNSConfig, nopt netproviders.Opt, apparmorProfile string, selinux bool, parallelismSem *semaphore.Weighted, traceSocket string, opts ...containerd.ClientOpt) (base.WorkerOpt, error) { +func NewWorkerOpt(root string, address, snapshotterName, ns string, rootless bool, labels map[string]string, dns *networks.DNSConfig, nopt netproviders.Opt, apparmorProfile string, selinux bool, parallelismSem *semaphore.Weighted, traceSocket string, opts ...containerd.ClientOpt) (base.WorkerOpt, error) { opts = append(opts, containerd.WithDefaultNamespace(ns)) client, err := containerd.New(address, opts...) if err != nil { @@ -36,7 +36,7 @@ func NewWorkerOpt(root string, address, snapshotterName, ns string, rootless boo return newContainerd(root, client, snapshotterName, ns, rootless, labels, dns, nopt, apparmorProfile, selinux, parallelismSem, traceSocket) } -func newContainerd(root string, client *containerd.Client, snapshotterName, ns string, rootless bool, labels map[string]string, dns *oci.DNSConfig, nopt netproviders.Opt, apparmorProfile string, selinux bool, parallelismSem *semaphore.Weighted, traceSocket string) (base.WorkerOpt, error) { +func newContainerd(root string, client *containerd.Client, snapshotterName, ns string, rootless bool, labels map[string]string, dns *networks.DNSConfig, nopt netproviders.Opt, apparmorProfile string, selinux bool, parallelismSem *semaphore.Weighted, traceSocket string) (base.WorkerOpt, error) { if strings.Contains(snapshotterName, "/") { return base.WorkerOpt{}, errors.Errorf("bad snapshotter name: %q", snapshotterName) } @@ -137,6 +137,7 @@ func newContainerd(root string, client *containerd.Client, snapshotterName, ns s Labels: xlabels, MetadataStore: md, NetworkProviders: np, + DNSConfig: dns, Executor: containerdexecutor.New(client, root, "", np, dns, apparmorProfile, selinux, traceSocket, rootless), Snapshotter: snap, ContentStore: cs, diff --git a/worker/runc/runc.go b/worker/runc/runc.go index 974dfab3a05d..f08ba4a62388 100644 --- a/worker/runc/runc.go +++ b/worker/runc/runc.go @@ -18,6 +18,7 @@ import ( "github.com/moby/buildkit/executor/oci" "github.com/moby/buildkit/executor/resources" "github.com/moby/buildkit/executor/runcexecutor" + "github.com/moby/buildkit/session/networks" containerdsnapshot "github.com/moby/buildkit/snapshot/containerd" "github.com/moby/buildkit/util/leaseutil" "github.com/moby/buildkit/util/network/netproviders" @@ -36,7 +37,7 @@ type SnapshotterFactory struct { } // NewWorkerOpt creates a WorkerOpt. -func NewWorkerOpt(root string, snFactory SnapshotterFactory, rootless bool, processMode oci.ProcessMode, labels map[string]string, idmap *idtools.IdentityMapping, nopt netproviders.Opt, dns *oci.DNSConfig, binary, apparmorProfile string, selinux bool, parallelismSem *semaphore.Weighted, traceSocket, defaultCgroupParent string) (base.WorkerOpt, error) { +func NewWorkerOpt(root string, snFactory SnapshotterFactory, rootless bool, processMode oci.ProcessMode, labels map[string]string, idmap *idtools.IdentityMapping, nopt netproviders.Opt, dns *networks.DNSConfig, binary, apparmorProfile string, selinux bool, parallelismSem *semaphore.Weighted, traceSocket, defaultCgroupParent string) (base.WorkerOpt, error) { var opt base.WorkerOpt name := "runc-" + snFactory.Name root = filepath.Join(root, name) @@ -150,6 +151,7 @@ func NewWorkerOpt(root string, snFactory SnapshotterFactory, rootless bool, proc Labels: xlabels, MetadataStore: md, NetworkProviders: np, + DNSConfig: dns, Executor: exe, Snapshotter: snap, ContentStore: c,