diff --git a/cmd/buildctl/build.go b/cmd/buildctl/build.go index 5b2d72ef7635..f5fd205a9901 100644 --- a/cmd/buildctl/build.go +++ b/cmd/buildctl/build.go @@ -4,8 +4,10 @@ import ( "context" "encoding/base64" "encoding/json" + "fmt" "io" "os" + "strings" "github.com/containerd/continuity" "github.com/docker/cli/cli/config" @@ -13,6 +15,7 @@ import ( "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/cmd/buildctl/build" bccommon "github.com/moby/buildkit/cmd/buildctl/common" + gateway "github.com/moby/buildkit/frontend/gateway/client" "github.com/moby/buildkit/session" "github.com/moby/buildkit/session/auth/authprovider" "github.com/moby/buildkit/session/sshforward/sshprovider" @@ -262,13 +265,40 @@ func buildAction(clicontext *cli.Context) error { } } + var subMetadata map[string][]byte + eg.Go(func() error { defer func() { for _, w := range writers { close(w.Status()) } }() - resp, err := c.Solve(ctx, def, solveOpt, progresswriter.ResetTime(mw.WithPrefix("", false)).Status()) + sreq := gateway.SolveRequest{ + Frontend: solveOpt.Frontend, + FrontendOpt: solveOpt.FrontendAttrs, + } + if def != nil { + sreq.Definition = def.ToPB() + } + solveOpt.Frontend = "" + solveOpt.FrontendAttrs = nil + + resp, err := c.Build(ctx, solveOpt, "buildctl", func(ctx context.Context, c gateway.Client) (*gateway.Result, error) { + _, isSubRequest := sreq.FrontendOpt["requestid"] + if isSubRequest { + if _, ok := sreq.FrontendOpt["frontend.caps"]; !ok { + sreq.FrontendOpt["frontend.caps"] = "moby.buildkit.frontend.subrequests" + } + } + res, err := c.Solve(ctx, sreq) + if err != nil { + return nil, err + } + if isSubRequest && res != nil { + subMetadata = res.Metadata + } + return res, err + }, progresswriter.ResetTime(mw.WithPrefix("", false)).Status()) if err != nil { return err } @@ -291,7 +321,20 @@ func buildAction(clicontext *cli.Context) error { return pw.Err() }) - return eg.Wait() + if err := eg.Wait(); err != nil { + return err + } + + if txt, ok := subMetadata["result.txt"]; ok { + fmt.Print(string(txt)) + } else { + for k, v := range subMetadata { + if strings.HasPrefix(k, "result.") { + fmt.Printf("%s\n%s\n", k, v) + } + } + } + return nil } func writeMetadataFile(filename string, exporterResponse map[string]string) error { diff --git a/frontend/dockerfile/builder/build.go b/frontend/dockerfile/builder/build.go index 4a5dcc3f1874..88106b63088e 100644 --- a/frontend/dockerfile/builder/build.go +++ b/frontend/dockerfile/builder/build.go @@ -24,6 +24,8 @@ import ( "github.com/moby/buildkit/frontend/dockerfile/parser" "github.com/moby/buildkit/frontend/gateway/client" gwpb "github.com/moby/buildkit/frontend/gateway/pb" + "github.com/moby/buildkit/frontend/subrequests/outline" + "github.com/moby/buildkit/frontend/subrequests/targets" "github.com/moby/buildkit/solver/errdefs" "github.com/moby/buildkit/solver/pb" binfotypes "github.com/moby/buildkit/util/buildinfo/types" @@ -60,6 +62,7 @@ const ( keyShmSize = "shm-size" keyTargetPlatform = "platform" keyUlimit = "ulimit" + keyRequestID = "requestid" // Don't forget to update frontend documentation if you add // a new build-arg: frontend/dockerfile/docs/reference.md @@ -72,7 +75,7 @@ const ( var httpPrefix = regexp.MustCompile(`^https?://`) -func Build(ctx context.Context, c client.Client) (*client.Result, error) { +func Build(ctx context.Context, c client.Client) (_ *client.Result, err error) { opts := c.BuildOpts().Opts caps := c.BuildOpts().LLBCaps gwcaps := c.BuildOpts().Caps @@ -420,49 +423,72 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) { opts[keyHostname] = v } + convertOpt := dockerfile2llb.ConvertOpt{ + Target: opts[keyTarget], + MetaResolver: c, + BuildArgs: filter(opts, buildArgPrefix), + Labels: filter(opts, labelPrefix), + CacheIDNamespace: opts[keyCacheNSArg], + SessionID: c.BuildOpts().SessionID, + BuildContext: buildContext, + Excludes: excludes, + IgnoreCache: ignoreCache, + TargetPlatform: targetPlatforms[0], + BuildPlatforms: buildPlatforms, + ImageResolveMode: resolveMode, + PrefixPlatform: exportMap, + ExtraHosts: extraHosts, + ShmSize: shmSize, + Ulimit: ulimit, + CgroupParent: opts[keyCgroupParent], + ForceNetMode: defaultNetMode, + LLBCaps: &caps, + SourceMap: sourceMap, + Hostname: opts[keyHostname], + Warn: func(msg, url string, detail [][]byte, location *parser.Range) { + c.Warn(ctx, defVtx, msg, warnOpts(sourceMap, location, detail, url)) + }, + ContextByName: contextByNameFunc(c, c.BuildOpts().SessionID, targetPlatforms[0]), + } + + defer func() { + var el *parser.ErrorLocation + if errors.As(err, &el) { + err = wrapSource(err, sourceMap, el.Location) + } + }() + + if req, ok := opts[keyRequestID]; ok { + switch req { + case outline.SubrequestsOutlineDefinition.Name: + o, err := dockerfile2llb.Dockefile2Outline(ctx, dtDockerfile, convertOpt) + if err != nil { + return nil, err + } + return o.ToResult() + case targets.SubrequestsTargetsDefinition.Name: + targets, err := dockerfile2llb.ListTargets(ctx, dtDockerfile) + if err != nil { + return nil, err + } + return targets.ToResult() + default: + return nil, errdefs.NewUnsupportedSubrequestError(req) + } + } + eg, ctx = errgroup.WithContext(ctx) for i, tp := range targetPlatforms { func(i int, tp *ocispecs.Platform) { eg.Go(func() (err error) { - defer func() { - var el *parser.ErrorLocation - if errors.As(err, &el) { - err = wrapSource(err, sourceMap, el.Location) - } - }() - - st, img, bi, err := dockerfile2llb.Dockerfile2LLB(ctx, dtDockerfile, dockerfile2llb.ConvertOpt{ - Target: opts[keyTarget], - MetaResolver: c, - BuildArgs: filter(opts, buildArgPrefix), - Labels: filter(opts, labelPrefix), - CacheIDNamespace: opts[keyCacheNSArg], - SessionID: c.BuildOpts().SessionID, - BuildContext: buildContext, - Excludes: excludes, - IgnoreCache: ignoreCache, - TargetPlatform: tp, - BuildPlatforms: buildPlatforms, - ImageResolveMode: resolveMode, - PrefixPlatform: exportMap, - ExtraHosts: extraHosts, - ShmSize: shmSize, - Ulimit: ulimit, - CgroupParent: opts[keyCgroupParent], - ForceNetMode: defaultNetMode, - LLBCaps: &caps, - SourceMap: sourceMap, - Hostname: opts[keyHostname], - Warn: func(msg, url string, detail [][]byte, location *parser.Range) { - if i != 0 { - return - } - c.Warn(ctx, defVtx, msg, warnOpts(sourceMap, location, detail, url)) - }, - ContextByName: contextByNameFunc(c, c.BuildOpts().SessionID, tp), - }) - + opt := convertOpt + opt.TargetPlatform = tp + if i != 0 { + opt.Warn = nil + } + opt.ContextByName = contextByNameFunc(c, c.BuildOpts().SessionID, tp) + st, img, bi, err := dockerfile2llb.Dockerfile2LLB(ctx, dtDockerfile, opt) if err != nil { return err } diff --git a/frontend/dockerfile/builder/subrequests.go b/frontend/dockerfile/builder/subrequests.go index 6d30b7b8cc1c..844953023822 100644 --- a/frontend/dockerfile/builder/subrequests.go +++ b/frontend/dockerfile/builder/subrequests.go @@ -1,16 +1,19 @@ package builder import ( + "bytes" "context" "encoding/json" "github.com/moby/buildkit/frontend/gateway/client" "github.com/moby/buildkit/frontend/subrequests" + "github.com/moby/buildkit/frontend/subrequests/outline" + "github.com/moby/buildkit/frontend/subrequests/targets" "github.com/moby/buildkit/solver/errdefs" ) func checkSubRequest(ctx context.Context, opts map[string]string) (*client.Result, bool, error) { - req, ok := opts["requestid"] + req, ok := opts[keyRequestID] if !ok { return nil, false, nil } @@ -18,6 +21,8 @@ func checkSubRequest(ctx context.Context, opts map[string]string) (*client.Resul case subrequests.RequestSubrequestsDescribe: res, err := describe() return res, true, err + case outline.RequestSubrequestsOutline, targets.RequestTargets: // handled later + return nil, false, nil default: return nil, true, errdefs.NewUnsupportedSubrequestError(req) } @@ -25,15 +30,25 @@ func checkSubRequest(ctx context.Context, opts map[string]string) (*client.Resul func describe() (*client.Result, error) { all := []subrequests.Request{ + outline.SubrequestsOutlineDefinition, + targets.SubrequestsTargetsDefinition, subrequests.SubrequestsDescribeDefinition, } - dt, err := json.MarshalIndent(all, " ", "") + dt, err := json.MarshalIndent(all, "", " ") if err != nil { return nil, err } + + b := bytes.NewBuffer(nil) + if err := subrequests.PrintDescribe(dt, b); err != nil { + return nil, err + } + res := client.NewResult() res.Metadata = map[string][]byte{ "result.json": dt, + "result.txt": b.Bytes(), + "version": []byte(subrequests.SubrequestsDescribeDefinition.Version), } return res, nil } diff --git a/frontend/dockerfile/dockerfile2llb/convert.go b/frontend/dockerfile/dockerfile2llb/convert.go index a5b7d3e5f9cb..07dbfa87b8d3 100644 --- a/frontend/dockerfile/dockerfile2llb/convert.go +++ b/frontend/dockerfile/dockerfile2llb/convert.go @@ -23,6 +23,8 @@ import ( "github.com/moby/buildkit/frontend/dockerfile/instructions" "github.com/moby/buildkit/frontend/dockerfile/parser" "github.com/moby/buildkit/frontend/dockerfile/shell" + "github.com/moby/buildkit/frontend/subrequests/outline" + "github.com/moby/buildkit/frontend/subrequests/targets" "github.com/moby/buildkit/identity" "github.com/moby/buildkit/solver/pb" "github.com/moby/buildkit/util/apicaps" @@ -73,6 +75,51 @@ type ConvertOpt struct { } func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, *Image, *binfotypes.BuildInfo, error) { + ds, bi, err := toDispatchState(ctx, dt, opt) + if err != nil { + return nil, nil, nil, err + } + return &ds.state, &ds.image, bi, nil +} + +func Dockefile2Outline(ctx context.Context, dt []byte, opt ConvertOpt) (*outline.Outline, error) { + ds, _, err := toDispatchState(ctx, dt, opt) + if err != nil { + return nil, err + } + o := ds.Outline(dt) + return &o, nil +} + +func ListTargets(ctx context.Context, dt []byte) (*targets.List, error) { + dockerfile, err := parser.Parse(bytes.NewReader(dt)) + if err != nil { + return nil, err + } + stages, _, err := instructions.Parse(dockerfile.AST) + if err != nil { + return nil, err + } + + l := &targets.List{ + Sources: [][]byte{dt}, + } + + for i, s := range stages { + t := targets.Target{ + Name: s.Name, + Description: s.Comment, + Default: i == len(stages)-1, + Base: s.BaseName, + Platform: s.Platform, + Location: toSourceLocation(s.Location), + } + l.Targets = append(l.Targets, t) + } + return l, nil +} + +func toDispatchState(ctx context.Context, dt []byte, opt ConvertOpt) (*dispatchState, *binfotypes.BuildInfo, error) { buildInfo := &binfotypes.BuildInfo{} buildInfoDepsMu := sync.Mutex{} contextByName := opt.ContextByName @@ -100,7 +147,7 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, } if len(dt) == 0 { - return nil, nil, nil, errors.Errorf("the Dockerfile cannot be empty") + return nil, nil, errors.Errorf("the Dockerfile cannot be empty") } if opt.ContextLocalName == "" { @@ -116,7 +163,7 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, dockerfile, err := parser.Parse(bytes.NewReader(dt)) if err != nil { - return nil, nil, nil, err + return nil, nil, err } for _, w := range dockerfile.Warnings { @@ -127,17 +174,27 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, stages, metaArgs, err := instructions.Parse(dockerfile.AST) if err != nil { - return nil, nil, nil, err + return nil, nil, err } shlex := shell.NewLex(dockerfile.EscapeToken) + outline := newOutlineCapture() for _, cmd := range metaArgs { for _, metaArg := range cmd.Args { + info := argInfo{definition: metaArg, location: cmd.Location()} + if v, ok := opt.BuildArgs[metaArg.Key]; !ok { + if metaArg.Value != nil { + *metaArg.Value, info.deps, _ = shlex.ProcessWordWithMatches(*metaArg.Value, metaArgsToMap(optMetaArgs)) + } + } else { + metaArg.Value = &v + } + optMetaArgs = append(optMetaArgs, metaArg) if metaArg.Value != nil { - *metaArg.Value, _ = shlex.ProcessWordWithMap(*metaArg.Value, metaArgsToMap(optMetaArgs)) + info.value = *metaArg.Value } - optMetaArgs = append(optMetaArgs, setKVValue(metaArg, opt.BuildArgs)) + outline.allArgs[metaArg.Key] = info } } @@ -150,12 +207,12 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, // set base state for every image for i, st := range stages { - name, err := shlex.ProcessWordWithMap(st.BaseName, metaArgsToMap(optMetaArgs)) + name, used, err := shlex.ProcessWordWithMatches(st.BaseName, metaArgsToMap(optMetaArgs)) if err != nil { - return nil, nil, nil, parser.WithLocation(err, st.Location) + return nil, nil, parser.WithLocation(err, st.Location) } if name == "" { - return nil, nil, nil, parser.WithLocation(errors.Errorf("base name (%s) should not be blank", st.BaseName), st.Location) + return nil, nil, parser.WithLocation(errors.Errorf("base name (%s) should not be blank", st.BaseName), st.Location) } st.BaseName = name @@ -165,12 +222,13 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, ctxPaths: make(map[string]struct{}), stageName: st.Name, prefixPlatform: opt.PrefixPlatform, + outline: outline.clone(), } if st.Name != "" { s, img, bi, err := opt.ContextByName(ctx, st.Name, opt.ImageResolveMode.String()) if err != nil { - return nil, nil, nil, err + return nil, nil, err } if s != nil { ds.noinit = true @@ -198,19 +256,26 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, } if v := st.Platform; v != "" { - v, err := shlex.ProcessWordWithMap(v, metaArgsToMap(optMetaArgs)) + v, u, err := shlex.ProcessWordWithMatches(v, metaArgsToMap(optMetaArgs)) if err != nil { - return nil, nil, nil, parser.WithLocation(errors.Wrapf(err, "failed to process arguments for platform %s", v), st.Location) + return nil, nil, parser.WithLocation(errors.Wrapf(err, "failed to process arguments for platform %s", v), st.Location) } p, err := platforms.Parse(v) if err != nil { - return nil, nil, nil, parser.WithLocation(errors.Wrapf(err, "failed to parse platform %s", v), st.Location) + return nil, nil, parser.WithLocation(errors.Wrapf(err, "failed to parse platform %s", v), st.Location) + } + for k := range u { + used[k] = struct{}{} } ds.platform = &p } allDispatchStates.addState(ds) + for k := range used { + ds.outline.usedArgs[k] = struct{}{} + } + total := 0 if ds.stage.BaseName != emptyImageName && ds.base == nil { total = 1 @@ -245,7 +310,7 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, var ok bool target, ok = allDispatchStates.findStateByName(opt.Target) if !ok { - return nil, nil, nil, errors.Errorf("target stage %s could not be found", opt.Target) + return nil, nil, errors.Errorf("target stage %s could not be found", opt.Target) } } @@ -255,7 +320,7 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, for i, cmd := range d.stage.Commands { newCmd, err := toCommand(cmd, allDispatchStates) if err != nil { - return nil, nil, nil, err + return nil, nil, err } d.commands[i] = newCmd for _, src := range newCmd.sources { @@ -270,7 +335,7 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, } if has, state := hasCircularDependency(allDispatchStates.states); has { - return nil, nil, nil, errors.Errorf("circular dependency detected on stage: %s", state.stageName) + return nil, nil, errors.Errorf("circular dependency detected on stage: %s", state.stageName) } if len(allDispatchStates.states) == 1 { @@ -403,7 +468,7 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, } if err := eg.Wait(); err != nil { - return nil, nil, nil, err + return nil, nil, err } buildContext := &mutableOutput{} @@ -452,12 +517,12 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, } if d.image.Config.WorkingDir != "" { if err = dispatchWorkdir(d, &instructions.WorkdirCommand{Path: d.image.Config.WorkingDir}, false, nil); err != nil { - return nil, nil, nil, parser.WithLocation(err, d.stage.Location) + return nil, nil, parser.WithLocation(err, d.stage.Location) } } if d.image.Config.User != "" { if err = dispatchUser(d, &instructions.UserCommand{User: d.image.Config.User}, false); err != nil { - return nil, nil, nil, parser.WithLocation(err, d.stage.Location) + return nil, nil, parser.WithLocation(err, d.stage.Location) } } d.state = d.state.Network(opt.ForceNetMode) @@ -482,13 +547,13 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, } if err = dispatchOnBuildTriggers(d, d.image.Config.OnBuild, opt); err != nil { - return nil, nil, nil, parser.WithLocation(err, d.stage.Location) + return nil, nil, parser.WithLocation(err, d.stage.Location) } d.image.Config.OnBuild = nil for _, cmd := range d.commands { if err := dispatch(d, cmd, opt); err != nil { - return nil, nil, nil, parser.WithLocation(err, cmd.Location()) + return nil, nil, parser.WithLocation(err, cmd.Location()) } } @@ -533,7 +598,7 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, if opt.LLBCaps != nil { defaults = append(defaults, llb.WithCaps(*opt.LLBCaps)) } - st := target.state.SetMarshalDefaults(defaults...) + target.state = target.state.SetMarshalDefaults(defaults...) if !platformOpt.implicitTarget { target.image.OS = platformOpt.targetPlatform.OS @@ -541,7 +606,7 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, target.image.Variant = platformOpt.targetPlatform.Variant } - return &st, &target.image, buildInfo, nil + return target, buildInfo, nil } func metaArgsToMap(metaArgs []instructions.KeyValuePairOptional) map[string]string { @@ -731,6 +796,7 @@ type dispatchState struct { cmdTotal int prefixPlatform bool buildInfo binfotypes.BuildInfo + outline outlineCapture } type dispatchStates struct { @@ -747,6 +813,7 @@ func (dss *dispatchStates) addState(ds *dispatchState) { if d, ok := dss.statesByName[ds.stage.BaseName]; ok { ds.base = d + ds.outline = d.outline.clone() } if ds.stage.Name != "" { dss.statesByName[strings.ToLower(ds.stage.Name)] = ds @@ -1294,17 +1361,28 @@ func dispatchArg(d *dispatchState, c *instructions.ArgCommand, metaArgs []instru commitStr += "=" + *arg.Value } commitStrs = append(commitStrs, commitStr) + + skipArgInfo := false // skip the arg info if the arg is inherited from global scope if buildArg.Value == nil { for _, ma := range metaArgs { if ma.Key == buildArg.Key { buildArg.Value = ma.Value + skipArgInfo = true } } } + ai := argInfo{definition: arg, location: c.Location()} + if buildArg.Value != nil { d.state = d.state.AddEnv(buildArg.Key, *buildArg.Value) + ai.value = *buildArg.Value + } + + if !skipArgInfo { + d.outline.allArgs[arg.Key] = ai } + d.outline.usedArgs[arg.Key] = struct{}{} d.buildArgs = append(d.buildArgs, buildArg) } diff --git a/frontend/dockerfile/dockerfile2llb/convert_runmount.go b/frontend/dockerfile/dockerfile2llb/convert_runmount.go index 0464c68fcb8e..1015590a0dc6 100644 --- a/frontend/dockerfile/dockerfile2llb/convert_runmount.go +++ b/frontend/dockerfile/dockerfile2llb/convert_runmount.go @@ -79,7 +79,7 @@ func dispatchRunMounts(d *dispatchState, c *instructions.RunCommand, sources []* )) } if mount.Type == instructions.MountTypeSecret { - secret, err := dispatchSecret(mount) + secret, err := dispatchSecret(d, mount, c.Location()) if err != nil { return nil, err } @@ -87,7 +87,7 @@ func dispatchRunMounts(d *dispatchState, c *instructions.RunCommand, sources []* continue } if mount.Type == instructions.MountTypeSSH { - ssh, err := dispatchSSH(mount) + ssh, err := dispatchSSH(d, mount, c.Location()) if err != nil { return nil, err } diff --git a/frontend/dockerfile/dockerfile2llb/convert_secrets.go b/frontend/dockerfile/dockerfile2llb/convert_secrets.go index 2c88a5e4f7e7..ced2bff1b070 100644 --- a/frontend/dockerfile/dockerfile2llb/convert_secrets.go +++ b/frontend/dockerfile/dockerfile2llb/convert_secrets.go @@ -5,10 +5,11 @@ import ( "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/frontend/dockerfile/instructions" + "github.com/moby/buildkit/frontend/dockerfile/parser" "github.com/pkg/errors" ) -func dispatchSecret(m *instructions.Mount) (llb.RunOption, error) { +func dispatchSecret(d *dispatchState, m *instructions.Mount, loc []parser.Range) (llb.RunOption, error) { id := m.CacheID if m.Source != "" { id = m.Source @@ -26,6 +27,13 @@ func dispatchSecret(m *instructions.Mount) (llb.RunOption, error) { target = "/run/secrets/" + path.Base(id) } + if _, ok := d.outline.secrets[id]; !ok { + d.outline.secrets[id] = secretInfo{ + location: loc, + required: m.Required, + } + } + opts := []llb.SecretOption{llb.SecretID(id)} if !m.Required { diff --git a/frontend/dockerfile/dockerfile2llb/convert_ssh.go b/frontend/dockerfile/dockerfile2llb/convert_ssh.go index b55659d97883..ab7aaa60127f 100644 --- a/frontend/dockerfile/dockerfile2llb/convert_ssh.go +++ b/frontend/dockerfile/dockerfile2llb/convert_ssh.go @@ -3,13 +3,26 @@ package dockerfile2llb import ( "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/frontend/dockerfile/instructions" + "github.com/moby/buildkit/frontend/dockerfile/parser" "github.com/pkg/errors" ) -func dispatchSSH(m *instructions.Mount) (llb.RunOption, error) { +func dispatchSSH(d *dispatchState, m *instructions.Mount, loc []parser.Range) (llb.RunOption, error) { if m.Source != "" { return nil, errors.Errorf("ssh does not support source") } + + id := m.CacheID + if id == "" { + id = "default" + } + if _, ok := d.outline.ssh[id]; !ok { + d.outline.ssh[id] = sshInfo{ + location: loc, + required: m.Required, + } + } + opts := []llb.SSHOption{llb.SSHID(m.CacheID)} if m.Target != "" { diff --git a/frontend/dockerfile/dockerfile2llb/outline.go b/frontend/dockerfile/dockerfile2llb/outline.go new file mode 100644 index 000000000000..f93c8961b2ec --- /dev/null +++ b/frontend/dockerfile/dockerfile2llb/outline.go @@ -0,0 +1,210 @@ +package dockerfile2llb + +import ( + "sort" + + "github.com/moby/buildkit/frontend/dockerfile/instructions" + "github.com/moby/buildkit/frontend/dockerfile/parser" + "github.com/moby/buildkit/frontend/subrequests/outline" + pb "github.com/moby/buildkit/solver/pb" +) + +type outlineCapture struct { + allArgs map[string]argInfo + usedArgs map[string]struct{} + secrets map[string]secretInfo + ssh map[string]sshInfo +} + +type argInfo struct { + value string + definition instructions.KeyValuePairOptional + deps map[string]struct{} + location []parser.Range +} + +type secretInfo struct { + required bool + location []parser.Range +} + +type sshInfo struct { + required bool + location []parser.Range +} + +func newOutlineCapture() outlineCapture { + return outlineCapture{ + allArgs: map[string]argInfo{}, + usedArgs: map[string]struct{}{}, + secrets: map[string]secretInfo{}, + ssh: map[string]sshInfo{}, + } +} + +func (o outlineCapture) clone() outlineCapture { + allArgs := map[string]argInfo{} + for k, v := range o.allArgs { + allArgs[k] = v + } + usedArgs := map[string]struct{}{} + for k := range o.usedArgs { + usedArgs[k] = struct{}{} + } + secrets := map[string]secretInfo{} + for k, v := range o.secrets { + secrets[k] = v + } + ssh := map[string]sshInfo{} + for k, v := range o.ssh { + ssh[k] = v + } + return outlineCapture{ + allArgs: allArgs, + usedArgs: usedArgs, + secrets: secrets, + ssh: ssh, + } +} + +func (o outlineCapture) markAllUsed(in map[string]struct{}) { + for k := range in { + if a, ok := o.allArgs[k]; ok { + o.markAllUsed(a.deps) + } + o.usedArgs[k] = struct{}{} + } +} + +func (ds *dispatchState) args(visited map[string]struct{}) []outline.Arg { + ds.outline.markAllUsed(ds.outline.usedArgs) + + args := make([]outline.Arg, 0, len(ds.outline.usedArgs)) + for k := range ds.outline.usedArgs { + if a, ok := ds.outline.allArgs[k]; ok { + if _, ok := visited[k]; !ok { + args = append(args, outline.Arg{ + Name: a.definition.Key, + Value: a.value, + Description: a.definition.Comment, + Location: toSourceLocation(a.location), + }) + visited[k] = struct{}{} + } + } + } + + if ds.base != nil { + args = append(args, ds.base.args(visited)...) + } + for d := range ds.deps { + args = append(args, d.args(visited)...) + } + + return args +} + +func (ds *dispatchState) secrets(visited map[string]struct{}) []outline.Secret { + secrets := make([]outline.Secret, 0, len(ds.outline.secrets)) + for k, v := range ds.outline.secrets { + if _, ok := visited[k]; !ok { + secrets = append(secrets, outline.Secret{ + Name: k, + Required: v.required, + Location: toSourceLocation(v.location), + }) + visited[k] = struct{}{} + } + } + if ds.base != nil { + secrets = append(secrets, ds.base.secrets(visited)...) + } + for d := range ds.deps { + secrets = append(secrets, d.secrets(visited)...) + } + return secrets +} + +func (ds *dispatchState) ssh(visited map[string]struct{}) []outline.SSH { + ssh := make([]outline.SSH, 0, len(ds.outline.secrets)) + for k, v := range ds.outline.ssh { + if _, ok := visited[k]; !ok { + ssh = append(ssh, outline.SSH{ + Name: k, + Required: v.required, + Location: toSourceLocation(v.location), + }) + visited[k] = struct{}{} + } + } + if ds.base != nil { + ssh = append(ssh, ds.base.ssh(visited)...) + } + for d := range ds.deps { + ssh = append(ssh, d.ssh(visited)...) + } + return ssh +} + +func (ds *dispatchState) Outline(dt []byte) outline.Outline { + args := ds.args(map[string]struct{}{}) + sort.Slice(args, func(i, j int) bool { + return compLocation(args[i].Location, args[j].Location) + }) + + secrets := ds.secrets(map[string]struct{}{}) + sort.Slice(secrets, func(i, j int) bool { + return compLocation(secrets[i].Location, secrets[j].Location) + }) + + ssh := ds.ssh(map[string]struct{}{}) + sort.Slice(ssh, func(i, j int) bool { + return compLocation(ssh[i].Location, ssh[j].Location) + }) + + out := outline.Outline{ + Name: ds.stage.Name, + Description: ds.stage.Comment, + Sources: [][]byte{dt}, + Args: args, + Secrets: secrets, + SSH: ssh, + } + + return out +} + +func toSourceLocation(r []parser.Range) *pb.Location { + if len(r) == 0 { + return nil + } + arr := make([]*pb.Range, len(r)) + for i, r := range r { + arr[i] = &pb.Range{ + Start: pb.Position{ + Line: int32(r.Start.Line), + Character: int32(r.Start.Character), + }, + End: pb.Position{ + Line: int32(r.End.Line), + Character: int32(r.End.Character), + }, + } + } + return &pb.Location{Ranges: arr} +} + +func compLocation(a, b *pb.Location) bool { + if a.SourceIndex != b.SourceIndex { + return a.SourceIndex < b.SourceIndex + } + linea := 0 + lineb := 0 + if len(a.Ranges) > 0 { + linea = int(a.Ranges[0].Start.Line) + } + if len(b.Ranges) > 0 { + lineb = int(b.Ranges[0].Start.Line) + } + return linea < lineb +} diff --git a/frontend/dockerfile/dockerfile_outline_test.go b/frontend/dockerfile/dockerfile_outline_test.go new file mode 100644 index 000000000000..df47ed65a2d7 --- /dev/null +++ b/frontend/dockerfile/dockerfile_outline_test.go @@ -0,0 +1,306 @@ +package dockerfile + +import ( + "context" + "encoding/json" + "os" + "testing" + + "github.com/containerd/continuity/fs/fstest" + "github.com/moby/buildkit/client" + "github.com/moby/buildkit/frontend/dockerfile/builder" + gateway "github.com/moby/buildkit/frontend/gateway/client" + "github.com/moby/buildkit/frontend/subrequests" + "github.com/moby/buildkit/frontend/subrequests/outline" + "github.com/moby/buildkit/util/testutil/integration" + "github.com/pkg/errors" + "github.com/stretchr/testify/require" +) + +var outlineTests = integration.TestFuncs( + testOutlineArgs, + testOutlineSecrets, + testOutlineDescribeDefinition, +) + +func testOutlineArgs(t *testing.T, sb integration.Sandbox) { + f := getFrontend(t, sb) + if _, ok := f.(*clientFrontend); !ok { + t.Skip("only test with client frontend") + } + + dockerfile := []byte(`ARG inherited=box +ARG inherited2=box2 +ARG unused=abc${inherited2} +# sfx is a suffix +ARG sfx="usy${inherited}" + +FROM b${sfx} AS first +# this is not assigned to anything +ARG FOO=123 +# BAR is a number +ARG BAR=456 +RUN true + +FROM alpine${unused} AS second +ARG BAZ +RUN true + +FROM scratch AS third +ARG ABC=a + +# target defines build target +FROM third AS target +COPY --from=first /etc/passwd / + +FROM second +`) + + dir, err := integration.Tmpdir( + t, + fstest.CreateFile("Dockerfile", []byte(dockerfile), 0600), + ) + require.NoError(t, err) + defer os.RemoveAll(dir) + + c, err := client.New(sb.Context(), sb.Address()) + require.NoError(t, err) + defer c.Close() + + destDir, err := os.MkdirTemp("", "buildkit") + require.NoError(t, err) + defer os.RemoveAll(destDir) + + called := false + frontend := func(ctx context.Context, c gateway.Client) (*gateway.Result, error) { + res, err := c.Solve(ctx, gateway.SolveRequest{ + FrontendOpt: map[string]string{ + "frontend.caps": "moby.buildkit.frontend.subrequests", + "requestid": "frontend.outline", + "build-arg:BAR": "678", + "target": "target", + }, + Frontend: "dockerfile.v0", + }) + require.NoError(t, err) + + outline, err := unmarshalOutline(res) + require.NoError(t, err) + + require.Equal(t, "target", outline.Name) + require.Equal(t, "defines build target", outline.Description) + + require.Equal(t, 1, len(outline.Sources)) + require.Equal(t, dockerfile, outline.Sources[0]) + + require.Equal(t, 5, len(outline.Args)) + + arg := outline.Args[0] + require.Equal(t, "inherited", arg.Name) + require.Equal(t, "box", arg.Value) + require.Equal(t, "", arg.Description) + require.Equal(t, int32(0), arg.Location.SourceIndex) + require.Equal(t, int32(1), arg.Location.Ranges[0].Start.Line) + + arg = outline.Args[1] + require.Equal(t, "sfx", arg.Name) + require.Equal(t, "usybox", arg.Value) + require.Equal(t, "is a suffix", arg.Description) + require.Equal(t, int32(5), arg.Location.Ranges[0].Start.Line) + + arg = outline.Args[2] + require.Equal(t, "FOO", arg.Name) + require.Equal(t, "123", arg.Value) + require.Equal(t, "", arg.Description) + require.Equal(t, int32(9), arg.Location.Ranges[0].Start.Line) + + arg = outline.Args[3] + require.Equal(t, "BAR", arg.Name) + require.Equal(t, "678", arg.Value) + require.Equal(t, "is a number", arg.Description) + + arg = outline.Args[4] + require.Equal(t, "ABC", arg.Name) + require.Equal(t, "a", arg.Value) + + called = true + return nil, nil + } + + _, err = c.Build(sb.Context(), client.SolveOpt{ + LocalDirs: map[string]string{ + builder.DefaultLocalNameDockerfile: dir, + }, + }, "", frontend, nil) + require.NoError(t, err) + + require.True(t, called) +} + +func testOutlineSecrets(t *testing.T, sb integration.Sandbox) { + f := getFrontend(t, sb) + if _, ok := f.(*clientFrontend); !ok { + t.Skip("only test with client frontend") + } + + dockerfile := []byte(` +FROM busybox AS first +RUN --mount=type=secret,target=/etc/passwd,required=true --mount=type=ssh true + +FROM alpine AS second +RUN --mount=type=secret,id=unused --mount=type=ssh,id=ssh2 true + +FROM scratch AS third +ARG BAR +RUN --mount=type=secret,id=second${BAR} true + +FROM third AS target +COPY --from=first /foo / +RUN --mount=type=ssh,id=ssh3,required true + +FROM second +`) + + dir, err := integration.Tmpdir( + t, + fstest.CreateFile("Dockerfile", []byte(dockerfile), 0600), + ) + require.NoError(t, err) + defer os.RemoveAll(dir) + + c, err := client.New(sb.Context(), sb.Address()) + require.NoError(t, err) + defer c.Close() + + destDir, err := os.MkdirTemp("", "buildkit") + require.NoError(t, err) + defer os.RemoveAll(destDir) + + called := false + frontend := func(ctx context.Context, c gateway.Client) (*gateway.Result, error) { + res, err := c.Solve(ctx, gateway.SolveRequest{ + FrontendOpt: map[string]string{ + "frontend.caps": "moby.buildkit.frontend.subrequests", + "requestid": "frontend.outline", + "build-arg:BAR": "678", + "target": "target", + }, + Frontend: "dockerfile.v0", + }) + require.NoError(t, err) + + outline, err := unmarshalOutline(res) + require.NoError(t, err) + + require.Equal(t, 1, len(outline.Sources)) + require.Equal(t, dockerfile, outline.Sources[0]) + + require.Equal(t, 2, len(outline.Secrets)) + + secret := outline.Secrets[0] + require.Equal(t, "passwd", secret.Name) + require.Equal(t, true, secret.Required) + require.Equal(t, int32(0), secret.Location.SourceIndex) + require.Equal(t, int32(3), secret.Location.Ranges[0].Start.Line) + + secret = outline.Secrets[1] + require.Equal(t, "second678", secret.Name) + require.Equal(t, false, secret.Required) + require.Equal(t, int32(0), secret.Location.SourceIndex) + require.Equal(t, int32(10), secret.Location.Ranges[0].Start.Line) + + require.Equal(t, 2, len(outline.SSH)) + + ssh := outline.SSH[0] + require.Equal(t, "default", ssh.Name) + require.Equal(t, false, ssh.Required) + require.Equal(t, int32(0), ssh.Location.SourceIndex) + require.Equal(t, int32(3), ssh.Location.Ranges[0].Start.Line) + + ssh = outline.SSH[1] + require.Equal(t, "ssh3", ssh.Name) + require.Equal(t, true, ssh.Required) + require.Equal(t, int32(0), ssh.Location.SourceIndex) + require.Equal(t, int32(14), ssh.Location.Ranges[0].Start.Line) + + called = true + return nil, nil + } + + _, err = c.Build(sb.Context(), client.SolveOpt{ + LocalDirs: map[string]string{ + builder.DefaultLocalNameDockerfile: dir, + }, + }, "", frontend, nil) + require.NoError(t, err) + + require.True(t, called) +} + +func testOutlineDescribeDefinition(t *testing.T, sb integration.Sandbox) { + f := getFrontend(t, sb) + if _, ok := f.(*clientFrontend); !ok { + t.Skip("only test with client frontend") + } + + c, err := client.New(sb.Context(), sb.Address()) + require.NoError(t, err) + defer c.Close() + + dockerfile := []byte(` +FROM scratch +COPY Dockerfile Dockerfile +`) + + dir, err := integration.Tmpdir( + t, + fstest.CreateFile("Dockerfile", dockerfile, 0600), + ) + require.NoError(t, err) + defer os.RemoveAll(dir) + + called := false + + frontend := func(ctx context.Context, c gateway.Client) (*gateway.Result, error) { + reqs, err := subrequests.Describe(ctx, c) + require.NoError(t, err) + + require.True(t, len(reqs) > 0) + + hasOutline := false + + for _, req := range reqs { + if req.Name != "frontend.outline" { + continue + } + hasOutline = true + require.Equal(t, subrequests.RequestType("rpc"), req.Type) + require.NotEqual(t, req.Version, "") + } + require.True(t, hasOutline) + + called = true + return nil, nil + } + + _, err = c.Build(sb.Context(), client.SolveOpt{ + LocalDirs: map[string]string{ + builder.DefaultLocalNameDockerfile: dir, + }, + }, "", frontend, nil) + require.NoError(t, err) + + require.True(t, called) +} + +func unmarshalOutline(res *gateway.Result) (*outline.Outline, error) { + dt, ok := res.Metadata["result.json"] + if !ok { + return nil, errors.Errorf("missing frontend.outline") + } + var o outline.Outline + if err := json.Unmarshal(dt, &o); err != nil { + return nil, err + } + return &o, nil +} diff --git a/frontend/dockerfile/dockerfile_targets_test.go b/frontend/dockerfile/dockerfile_targets_test.go new file mode 100644 index 000000000000..6b049f9ae77f --- /dev/null +++ b/frontend/dockerfile/dockerfile_targets_test.go @@ -0,0 +1,191 @@ +package dockerfile + +import ( + "context" + "encoding/json" + "os" + "testing" + + "github.com/containerd/continuity/fs/fstest" + "github.com/moby/buildkit/client" + "github.com/moby/buildkit/frontend/dockerfile/builder" + gateway "github.com/moby/buildkit/frontend/gateway/client" + "github.com/moby/buildkit/frontend/subrequests" + "github.com/moby/buildkit/frontend/subrequests/targets" + "github.com/moby/buildkit/util/testutil/integration" + "github.com/pkg/errors" + "github.com/stretchr/testify/require" +) + +var targetsTests = integration.TestFuncs( + testTargetsList, + testTargetsDescribeDefinition, +) + +func testTargetsList(t *testing.T, sb integration.Sandbox) { + f := getFrontend(t, sb) + if _, ok := f.(*clientFrontend); !ok { + t.Skip("only test with client frontend") + } + + dockerfile := []byte(` +# build defines stage for compiling the binary +FROM alpine AS build +RUN true + +FROM busybox as second +RUN false + +FROM alpine +RUN false + +# binary returns the compiled binary +FROM second AS binary +`) + + dir, err := integration.Tmpdir( + t, + fstest.CreateFile("Dockerfile", []byte(dockerfile), 0600), + ) + require.NoError(t, err) + defer os.RemoveAll(dir) + + c, err := client.New(sb.Context(), sb.Address()) + require.NoError(t, err) + defer c.Close() + + destDir, err := os.MkdirTemp("", "buildkit") + require.NoError(t, err) + defer os.RemoveAll(destDir) + + called := false + frontend := func(ctx context.Context, c gateway.Client) (*gateway.Result, error) { + res, err := c.Solve(ctx, gateway.SolveRequest{ + FrontendOpt: map[string]string{ + "frontend.caps": "moby.buildkit.frontend.subrequests", + "requestid": "frontend.targets", + }, + Frontend: "dockerfile.v0", + }) + require.NoError(t, err) + + list, err := unmarshalTargets(res) + require.NoError(t, err) + + require.Equal(t, 1, len(list.Sources)) + require.Equal(t, dockerfile, list.Sources[0]) + + require.Equal(t, 4, len(list.Targets)) + + target := list.Targets[0] + require.Equal(t, "build", target.Name) + require.Equal(t, "alpine", target.Base) + require.Equal(t, "defines stage for compiling the binary", target.Description) + require.Equal(t, false, target.Default) + require.Equal(t, int32(0), target.Location.SourceIndex) + require.Equal(t, int32(3), target.Location.Ranges[0].Start.Line) + + target = list.Targets[1] + require.Equal(t, "second", target.Name) + require.Equal(t, "", target.Description) + require.Equal(t, "busybox", target.Base) + require.Equal(t, false, target.Default) + require.Equal(t, int32(0), target.Location.SourceIndex) + require.Equal(t, int32(6), target.Location.Ranges[0].Start.Line) + + target = list.Targets[2] + require.Equal(t, "", target.Name) + require.Equal(t, "", target.Description) + require.Equal(t, "alpine", target.Base) + require.Equal(t, false, target.Default) + require.Equal(t, int32(0), target.Location.SourceIndex) + require.Equal(t, int32(9), target.Location.Ranges[0].Start.Line) + + target = list.Targets[3] + require.Equal(t, "binary", target.Name) + require.Equal(t, "returns the compiled binary", target.Description) + require.Equal(t, true, target.Default) + require.Equal(t, int32(0), target.Location.SourceIndex) + require.Equal(t, int32(13), target.Location.Ranges[0].Start.Line) + + called = true + return nil, nil + } + + _, err = c.Build(sb.Context(), client.SolveOpt{ + LocalDirs: map[string]string{ + builder.DefaultLocalNameDockerfile: dir, + }, + }, "", frontend, nil) + require.NoError(t, err) + + require.True(t, called) +} + +func testTargetsDescribeDefinition(t *testing.T, sb integration.Sandbox) { + f := getFrontend(t, sb) + if _, ok := f.(*clientFrontend); !ok { + t.Skip("only test with client frontend") + } + + c, err := client.New(sb.Context(), sb.Address()) + require.NoError(t, err) + defer c.Close() + + dockerfile := []byte(` +FROM scratch +COPY Dockerfile Dockerfile +`) + + dir, err := integration.Tmpdir( + t, + fstest.CreateFile("Dockerfile", dockerfile, 0600), + ) + require.NoError(t, err) + defer os.RemoveAll(dir) + + called := false + + frontend := func(ctx context.Context, c gateway.Client) (*gateway.Result, error) { + reqs, err := subrequests.Describe(ctx, c) + require.NoError(t, err) + + require.True(t, len(reqs) > 0) + + hasTargets := false + + for _, req := range reqs { + if req.Name != "frontend.targets" { + continue + } + hasTargets = true + require.Equal(t, subrequests.RequestType("rpc"), req.Type) + require.NotEqual(t, req.Version, "") + } + require.True(t, hasTargets) + + called = true + return nil, nil + } + + _, err = c.Build(sb.Context(), client.SolveOpt{ + LocalDirs: map[string]string{ + builder.DefaultLocalNameDockerfile: dir, + }, + }, "", frontend, nil) + require.NoError(t, err) + + require.True(t, called) +} + +func unmarshalTargets(res *gateway.Result) (*targets.List, error) { + dt, ok := res.Metadata["result.json"] + if !ok { + return nil, errors.Errorf("missing frontend.outline") + } + var l targets.List + if err := json.Unmarshal(dt, &l); err != nil { + return nil, err + } + return &l, nil +} diff --git a/frontend/dockerfile/dockerfile_test.go b/frontend/dockerfile/dockerfile_test.go index 118e4df5a9f6..b443fe1e05da 100644 --- a/frontend/dockerfile/dockerfile_test.go +++ b/frontend/dockerfile/dockerfile_test.go @@ -200,6 +200,8 @@ func TestIntegration(t *testing.T) { "denied": networkHostDenied, }))...) integration.Run(t, heredocTests, opts...) + integration.Run(t, outlineTests, opts...) + integration.Run(t, targetsTests, opts...) } func testDefaultEnvWithArgs(t *testing.T, sb integration.Sandbox) { @@ -4781,6 +4783,9 @@ COPY foo foo2 func testFrontendSubrequests(t *testing.T, sb integration.Sandbox) { f := getFrontend(t, sb) + if _, ok := f.(*clientFrontend); !ok { + t.Skip("only test with client frontend") + } c, err := client.New(sb.Context(), sb.Address()) require.NoError(t, err) @@ -4791,10 +4796,6 @@ FROM scratch COPY Dockerfile Dockerfile `) - if gf, ok := f.(*gatewayFrontend); ok { - dockerfile = []byte(fmt.Sprintf("#syntax=%s\n\n%s", gf.gw, dockerfile)) - } - dir, err := integration.Tmpdir( t, fstest.CreateFile("Dockerfile", dockerfile, 0600), @@ -4817,6 +4818,7 @@ COPY Dockerfile Dockerfile require.Equal(t, subrequests.RequestType("rpc"), req.Type) require.NotEqual(t, req.Version, "") require.True(t, len(req.Metadata) > 0) + require.Equal(t, "result.json", req.Metadata[0].Name) } } require.True(t, hasDescribe) diff --git a/frontend/subrequests/describe.go b/frontend/subrequests/describe.go index cc8053ed24d6..832c9a839ff9 100644 --- a/frontend/subrequests/describe.go +++ b/frontend/subrequests/describe.go @@ -3,6 +3,10 @@ package subrequests import ( "context" "encoding/json" + "fmt" + "io" + "strings" + "text/tabwriter" "github.com/moby/buildkit/frontend/gateway/client" gwpb "github.com/moby/buildkit/frontend/gateway/pb" @@ -18,9 +22,8 @@ var SubrequestsDescribeDefinition = Request{ Type: TypeRPC, Description: "List available subrequest types", Metadata: []Named{ - { - Name: "result.json", - }, + {Name: "result.json"}, + {Name: "result.txt"}, }, } @@ -61,3 +64,18 @@ func Describe(ctx context.Context, c client.Client) ([]Request, error) { } return reqs, nil } + +func PrintDescribe(dt []byte, w io.Writer) error { + var d []Request + if err := json.Unmarshal(dt, &d); err != nil { + return err + } + + tw := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0) + fmt.Fprintf(tw, "NAME\tVERSION\tDESCRIPTION\n") + + for _, r := range d { + fmt.Fprintf(tw, "%s\t%s\t%s\n", strings.TrimPrefix(r.Name, "frontend."), r.Version, r.Description) + } + return tw.Flush() +} diff --git a/frontend/subrequests/outline/outline.go b/frontend/subrequests/outline/outline.go new file mode 100644 index 000000000000..3050dc4b1376 --- /dev/null +++ b/frontend/subrequests/outline/outline.go @@ -0,0 +1,146 @@ +package outline + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "text/tabwriter" + + "github.com/moby/buildkit/frontend/gateway/client" + "github.com/moby/buildkit/frontend/subrequests" + "github.com/moby/buildkit/solver/pb" +) + +const RequestSubrequestsOutline = "frontend.outline" + +var SubrequestsOutlineDefinition = subrequests.Request{ + Name: RequestSubrequestsOutline, + Version: "1.0.0", + Type: subrequests.TypeRPC, + Description: "List all parameters current build target supports", + Opts: []subrequests.Named{ + { + Name: "target", + Description: "Target build stage", + }, + }, + Metadata: []subrequests.Named{ + {Name: "result.json"}, + {Name: "result.txt"}, + }, +} + +type Outline struct { + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Args []Arg `json:"args,omitempty"` + Secrets []Secret `json:"secrets,omitempty"` + SSH []SSH `json:"ssh,omitempty"` + Cache []CacheMount `json:"cache,omitempty"` + Sources [][]byte `json:"sources,omitempty"` +} + +func (o Outline) ToResult() (*client.Result, error) { + res := client.NewResult() + dt, err := json.MarshalIndent(o, "", " ") + if err != nil { + return nil, err + } + res.AddMeta("result.json", dt) + + b := bytes.NewBuffer(nil) + if err := PrintOutline(dt, b); err != nil { + return nil, err + } + res.AddMeta("result.txt", b.Bytes()) + + res.AddMeta("version", []byte(SubrequestsOutlineDefinition.Version)) + return res, nil +} + +type Arg struct { + Name string `json:"name"` + Description string `json:"description,omitempty"` + Value string `json:"value,omitempty"` + Location *pb.Location `json:"location,omitempty"` +} + +type Secret struct { + Name string `json:"name"` + Required bool `json:"required,omitempty"` + Location *pb.Location `json:"location,omitempty"` +} + +type SSH struct { + Name string `json:"name"` + Required bool `json:"required,omitempty"` + Location *pb.Location `json:"location,omitempty"` +} + +type CacheMount struct { + ID string `json:"ID"` + Location *pb.Location `json:"location,omitempty"` +} + +func PrintOutline(dt []byte, w io.Writer) error { + var o Outline + + if err := json.Unmarshal(dt, &o); err != nil { + return err + } + + if o.Name != "" || o.Description != "" { + tw := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0) + name := o.Name + if o.Name == "" { + name = "(default)" + } + fmt.Fprintf(tw, "TARGET:\t%s\n", name) + if o.Description != "" { + fmt.Fprintf(tw, "DESCRIPTION:\t%s\n", o.Description) + } + tw.Flush() + fmt.Println() + } + + if len(o.Args) > 0 { + tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0) + fmt.Fprintf(tw, "BUILD ARG\tVALUE\tDESCRIPTION\n") + for _, a := range o.Args { + fmt.Fprintf(tw, "%s\t%s\t%s\n", a.Name, a.Value, a.Description) + } + tw.Flush() + fmt.Println() + } + + if len(o.Secrets) > 0 { + tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0) + fmt.Fprintf(tw, "SECRET\tREQUIRED\n") + for _, s := range o.Secrets { + b := "" + if s.Required { + b = "true" + } + fmt.Fprintf(tw, "%s\t%s\n", s.Name, b) + } + tw.Flush() + fmt.Println() + } + + if len(o.SSH) > 0 { + tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0) + fmt.Fprintf(tw, "SSH\tREQUIRED\n") + for _, s := range o.SSH { + b := "" + if s.Required { + b = "true" + } + fmt.Fprintf(tw, "%s\t%s\n", s.Name, b) + } + tw.Flush() + fmt.Println() + } + + return nil +} diff --git a/frontend/subrequests/targets/targets.go b/frontend/subrequests/targets/targets.go new file mode 100644 index 000000000000..bf00a3b2bc96 --- /dev/null +++ b/frontend/subrequests/targets/targets.go @@ -0,0 +1,84 @@ +package targets + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "text/tabwriter" + + "github.com/moby/buildkit/frontend/gateway/client" + "github.com/moby/buildkit/frontend/subrequests" + "github.com/moby/buildkit/solver/pb" +) + +const RequestTargets = "frontend.targets" + +var SubrequestsTargetsDefinition = subrequests.Request{ + Name: RequestTargets, + Version: "1.0.0", + Type: subrequests.TypeRPC, + Description: "List all targets current build supports", + Opts: []subrequests.Named{}, + Metadata: []subrequests.Named{ + {Name: "result.json"}, + {Name: "result.txt"}, + }, +} + +type List struct { + Targets []Target `json:"targets"` + Sources [][]byte `json:"sources"` +} + +func (l List) ToResult() (*client.Result, error) { + res := client.NewResult() + dt, err := json.MarshalIndent(l, "", " ") + if err != nil { + return nil, err + } + res.AddMeta("result.json", dt) + + b := bytes.NewBuffer(nil) + if err := PrintTargets(dt, b); err != nil { + return nil, err + } + res.AddMeta("result.txt", b.Bytes()) + + res.AddMeta("version", []byte(SubrequestsTargetsDefinition.Version)) + return res, nil +} + +type Target struct { + Name string `json:"name,omitempty"` + Default bool `json:"default,omitempty"` + Description string `json:"description,omitempty"` + Base string `json:"base,omitempty"` + Platform string `json:"platform,omitempty"` + Location *pb.Location `json:"location,omitempty"` +} + +func PrintTargets(dt []byte, w io.Writer) error { + var l List + + if err := json.Unmarshal(dt, &l); err != nil { + return err + } + + tw := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0) + fmt.Fprintf(tw, "TARGET\tDESCRIPTION\n") + + for _, t := range l.Targets { + name := t.Name + if name == "" && t.Default { + name = "(default)" + } else { + if t.Default { + name = fmt.Sprintf("%s (default)", name) + } + } + fmt.Fprintf(tw, "%s\t%s\n", name, t.Description) + } + + return tw.Flush() +} diff --git a/solver/pb/ops.pb.go b/solver/pb/ops.pb.go index 68fda239415e..0cf15b077038 100644 --- a/solver/pb/ops.pb.go +++ b/solver/pb/ops.pb.go @@ -1586,8 +1586,8 @@ func (m *Range) GetEnd() Position { // Position is single location in a source file type Position struct { - Line int32 `protobuf:"varint,1,opt,name=Line,proto3" json:"Line,omitempty"` - Character int32 `protobuf:"varint,2,opt,name=Character,proto3" json:"Character,omitempty"` + Line int32 `protobuf:"varint,1,opt,name=line,proto3" json:"line,omitempty"` + Character int32 `protobuf:"varint,2,opt,name=character,proto3" json:"character,omitempty"` } func (m *Position) Reset() { *m = Position{} } @@ -2831,166 +2831,166 @@ func init() { func init() { proto.RegisterFile("ops.proto", fileDescriptor_8de16154b2733812) } var fileDescriptor_8de16154b2733812 = []byte{ - // 2538 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x59, 0xcf, 0x6f, 0x5b, 0xc7, - 0xf1, 0x17, 0x7f, 0x93, 0x43, 0x89, 0x66, 0xd6, 0x4e, 0xc2, 0xe8, 0xeb, 0xaf, 0xac, 0xbc, 0xe4, - 0x1b, 0xc8, 0xb2, 0x2d, 0xe1, 0xab, 0x00, 0x71, 0x60, 0x14, 0x45, 0x25, 0x91, 0x8e, 0x18, 0xdb, - 0xa2, 0xb0, 0xb4, 0x9d, 0x1e, 0x0a, 0x18, 0x4f, 0x8f, 0x4b, 0xe9, 0x41, 0x8f, 0x6f, 0x1f, 0xf6, - 0x2d, 0x23, 0xb1, 0x87, 0x1e, 0x7a, 0x2f, 0x10, 0xa0, 0x40, 0xd1, 0x4b, 0xd1, 0x7f, 0xa2, 0xc7, - 0xf6, 0x1e, 0xa0, 0x97, 0x1c, 0x7a, 0x08, 0x7a, 0x48, 0x0b, 0xe7, 0xd2, 0x3f, 0xa2, 0x05, 0x8a, - 0x99, 0xdd, 0xf7, 0x83, 0x94, 0x02, 0xc7, 0x6d, 0xd1, 0x13, 0xe7, 0xcd, 0x7c, 0x76, 0x66, 0x76, - 0x77, 0x66, 0x67, 0x76, 0x09, 0x0d, 0x19, 0xc5, 0x5b, 0x91, 0x92, 0x5a, 0xb2, 0x62, 0x74, 0xbc, - 0x7a, 0xef, 0xc4, 0xd7, 0xa7, 0xd3, 0xe3, 0x2d, 0x4f, 0x4e, 0xb6, 0x4f, 0xe4, 0x89, 0xdc, 0x26, - 0xd1, 0xf1, 0x74, 0x4c, 0x5f, 0xf4, 0x41, 0x94, 0x19, 0xe2, 0xfc, 0xad, 0x08, 0xc5, 0x41, 0xc4, - 0xde, 0x85, 0xaa, 0x1f, 0x46, 0x53, 0x1d, 0x77, 0x0a, 0xeb, 0xa5, 0x8d, 0xe6, 0x4e, 0x63, 0x2b, - 0x3a, 0xde, 0xea, 0x23, 0x87, 0x5b, 0x01, 0x5b, 0x87, 0xb2, 0xb8, 0x10, 0x5e, 0xa7, 0xb8, 0x5e, - 0xd8, 0x68, 0xee, 0x00, 0x02, 0x7a, 0x17, 0xc2, 0x1b, 0x44, 0x07, 0x4b, 0x9c, 0x24, 0xec, 0x03, - 0xa8, 0xc6, 0x72, 0xaa, 0x3c, 0xd1, 0x29, 0x11, 0x66, 0x19, 0x31, 0x43, 0xe2, 0x10, 0xca, 0x4a, - 0x51, 0xd3, 0xd8, 0x0f, 0x44, 0xa7, 0x9c, 0x69, 0x7a, 0xe8, 0x07, 0x06, 0x43, 0x12, 0xf6, 0x1e, - 0x54, 0x8e, 0xa7, 0x7e, 0x30, 0xea, 0x54, 0x08, 0xd2, 0x44, 0xc8, 0x1e, 0x32, 0x08, 0x63, 0x64, - 0x08, 0x9a, 0x08, 0x75, 0x22, 0x3a, 0xd5, 0x0c, 0xf4, 0x04, 0x19, 0x06, 0x44, 0x32, 0xb4, 0x35, - 0xf2, 0xc7, 0xe3, 0x4e, 0x2d, 0xb3, 0xd5, 0xf5, 0xc7, 0x63, 0x63, 0x0b, 0x25, 0x6c, 0x03, 0xea, - 0x51, 0xe0, 0xea, 0xb1, 0x54, 0x93, 0x0e, 0x64, 0x7e, 0x1f, 0x59, 0x1e, 0x4f, 0xa5, 0xec, 0x3e, - 0x34, 0x3d, 0x19, 0xc6, 0x5a, 0xb9, 0x7e, 0xa8, 0xe3, 0x4e, 0x93, 0xc0, 0x6f, 0x22, 0xf8, 0x33, - 0xa9, 0xce, 0x84, 0xda, 0xcf, 0x84, 0x3c, 0x8f, 0xdc, 0x2b, 0x43, 0x51, 0x46, 0xce, 0xaf, 0x0a, - 0x50, 0x4f, 0xb4, 0x32, 0x07, 0x96, 0x77, 0x95, 0x77, 0xea, 0x6b, 0xe1, 0xe9, 0xa9, 0x12, 0x9d, - 0xc2, 0x7a, 0x61, 0xa3, 0xc1, 0xe7, 0x78, 0xac, 0x05, 0xc5, 0xc1, 0x90, 0xd6, 0xbb, 0xc1, 0x8b, - 0x83, 0x21, 0xeb, 0x40, 0xed, 0xb9, 0xab, 0x7c, 0x37, 0xd4, 0xb4, 0xc0, 0x0d, 0x9e, 0x7c, 0xb2, - 0x9b, 0xd0, 0x18, 0x0c, 0x9f, 0x0b, 0x15, 0xfb, 0x32, 0xa4, 0x65, 0x6d, 0xf0, 0x8c, 0xc1, 0xd6, - 0x00, 0x06, 0xc3, 0x87, 0xc2, 0x45, 0xa5, 0x71, 0xa7, 0xb2, 0x5e, 0xda, 0x68, 0xf0, 0x1c, 0xc7, - 0xf9, 0x19, 0x54, 0x68, 0xab, 0xd9, 0xa7, 0x50, 0x1d, 0xf9, 0x27, 0x22, 0xd6, 0xc6, 0x9d, 0xbd, - 0x9d, 0x2f, 0xbf, 0xb9, 0xb5, 0xf4, 0xe7, 0x6f, 0x6e, 0x6d, 0xe6, 0x62, 0x4a, 0x46, 0x22, 0xf4, - 0x64, 0xa8, 0x5d, 0x3f, 0x14, 0x2a, 0xde, 0x3e, 0x91, 0xf7, 0xcc, 0x90, 0xad, 0x2e, 0xfd, 0x70, - 0xab, 0x81, 0xdd, 0x86, 0x8a, 0x1f, 0x8e, 0xc4, 0x05, 0xf9, 0x5f, 0xda, 0xbb, 0x6e, 0x55, 0x35, - 0x07, 0x53, 0x1d, 0x4d, 0x75, 0x1f, 0x45, 0xdc, 0x20, 0x9c, 0x3f, 0x16, 0xa0, 0x6a, 0x42, 0x89, - 0xdd, 0x84, 0xf2, 0x44, 0x68, 0x97, 0xec, 0x37, 0x77, 0xea, 0x66, 0x4b, 0xb5, 0xcb, 0x89, 0x8b, - 0x51, 0x3a, 0x91, 0x53, 0x5c, 0xfb, 0x62, 0x16, 0xa5, 0x4f, 0x90, 0xc3, 0xad, 0x80, 0xfd, 0x1f, - 0xd4, 0x42, 0xa1, 0xcf, 0xa5, 0x3a, 0xa3, 0x35, 0x6a, 0x99, 0xb0, 0x38, 0x14, 0xfa, 0x89, 0x1c, - 0x09, 0x9e, 0xc8, 0xd8, 0x5d, 0xa8, 0xc7, 0xc2, 0x9b, 0x2a, 0x5f, 0xcf, 0x68, 0xbd, 0x5a, 0x3b, - 0x6d, 0x0a, 0x56, 0xcb, 0x23, 0x70, 0x8a, 0x60, 0x77, 0xa0, 0x11, 0x0b, 0x4f, 0x09, 0x2d, 0xc2, - 0xcf, 0x69, 0xfd, 0x9a, 0x3b, 0x2b, 0x16, 0xae, 0x84, 0xee, 0x85, 0x9f, 0xf3, 0x4c, 0xee, 0xfc, - 0xa2, 0x08, 0x65, 0xf4, 0x99, 0x31, 0x28, 0xbb, 0xea, 0xc4, 0x64, 0x54, 0x83, 0x13, 0xcd, 0xda, - 0x50, 0x42, 0x1d, 0x45, 0x62, 0x21, 0x89, 0x1c, 0xef, 0x7c, 0x64, 0x37, 0x14, 0x49, 0x1c, 0x37, - 0x8d, 0x85, 0xb2, 0xfb, 0x48, 0x34, 0xbb, 0x0d, 0x8d, 0x48, 0xc9, 0x8b, 0xd9, 0x0b, 0xe3, 0x41, - 0x16, 0xa5, 0xc8, 0x44, 0x07, 0xea, 0x91, 0xa5, 0xd8, 0x26, 0x80, 0xb8, 0xd0, 0xca, 0x3d, 0x90, - 0xb1, 0x8e, 0x3b, 0x55, 0xf2, 0x96, 0xe2, 0x1e, 0x19, 0xfd, 0x23, 0x9e, 0x93, 0xb2, 0x55, 0xa8, - 0x9f, 0xca, 0x58, 0x87, 0xee, 0x44, 0x50, 0x86, 0x34, 0x78, 0xfa, 0xcd, 0x1c, 0xa8, 0x4e, 0x03, - 0x7f, 0xe2, 0xeb, 0x4e, 0x23, 0xd3, 0xf1, 0x8c, 0x38, 0xdc, 0x4a, 0x30, 0x8a, 0xbd, 0x13, 0x25, - 0xa7, 0xd1, 0x91, 0xab, 0x44, 0xa8, 0x29, 0x7f, 0x1a, 0x7c, 0x8e, 0xe7, 0xdc, 0x85, 0xaa, 0xb1, - 0x8c, 0x13, 0x43, 0xca, 0xc6, 0x3a, 0xd1, 0x18, 0xe3, 0xfd, 0xa3, 0x24, 0xc6, 0xfb, 0x47, 0x4e, - 0x17, 0xaa, 0xc6, 0x06, 0xa2, 0x0f, 0xd1, 0x2f, 0x8b, 0x46, 0x1a, 0x79, 0x43, 0x39, 0xd6, 0x26, - 0xa6, 0x38, 0xd1, 0xa4, 0xd5, 0x55, 0x66, 0x05, 0x4b, 0x9c, 0x68, 0xe7, 0x11, 0x34, 0xd2, 0xbd, - 0x21, 0x13, 0x5d, 0xab, 0xa6, 0xd8, 0xef, 0xe2, 0x00, 0x9a, 0xb0, 0x31, 0x4a, 0x34, 0x2e, 0x84, - 0x8c, 0xb4, 0x2f, 0x43, 0x37, 0x20, 0x45, 0x75, 0x9e, 0x7e, 0x3b, 0xbf, 0x2e, 0x41, 0x85, 0x82, - 0x8c, 0x6d, 0x60, 0x4c, 0x47, 0x53, 0x33, 0x83, 0xd2, 0x1e, 0xb3, 0x31, 0x0d, 0x94, 0x3d, 0x69, - 0x48, 0x63, 0x26, 0xad, 0x62, 0x7c, 0x05, 0xc2, 0xd3, 0x52, 0x59, 0x3b, 0xe9, 0x37, 0xda, 0x1f, - 0x61, 0x8e, 0x99, 0x2d, 0x27, 0x9a, 0xdd, 0x81, 0xaa, 0xa4, 0xc4, 0xa0, 0x5d, 0xff, 0x8e, 0x74, - 0xb1, 0x10, 0x54, 0xae, 0x84, 0x3b, 0x92, 0x61, 0x30, 0xa3, 0x58, 0xa8, 0xf3, 0xf4, 0x1b, 0x43, - 0x95, 0x32, 0xe1, 0xe9, 0x2c, 0x32, 0x07, 0x63, 0xcb, 0x84, 0xea, 0x93, 0x84, 0xc9, 0x33, 0x39, - 0x1e, 0x7d, 0x4f, 0x27, 0xd1, 0x38, 0x1e, 0x44, 0xba, 0x73, 0x3d, 0x0b, 0xaa, 0x84, 0xc7, 0x53, - 0x29, 0x22, 0x3d, 0xd7, 0x3b, 0x15, 0x88, 0xbc, 0x91, 0x21, 0xf7, 0x2d, 0x8f, 0xa7, 0xd2, 0x2c, - 0x57, 0x10, 0xfa, 0x26, 0x41, 0x73, 0xb9, 0x82, 0xd8, 0x4c, 0x8e, 0x31, 0x36, 0x1c, 0x1e, 0x20, - 0xf2, 0xad, 0xec, 0x7c, 0x36, 0x1c, 0x6e, 0x25, 0x66, 0xb6, 0xf1, 0x34, 0xd0, 0xfd, 0x6e, 0xe7, - 0x6d, 0xb3, 0x94, 0xc9, 0xb7, 0xb3, 0x96, 0x4d, 0x00, 0x97, 0x35, 0xf6, 0x7f, 0x6a, 0xe2, 0xa5, - 0xc4, 0x89, 0x76, 0xfa, 0x50, 0x4f, 0x5c, 0xbc, 0x14, 0x06, 0xf7, 0xa0, 0x16, 0x9f, 0xba, 0xca, - 0x0f, 0x4f, 0x68, 0x87, 0x5a, 0x3b, 0xd7, 0xd3, 0x19, 0x0d, 0x0d, 0x1f, 0xbd, 0x48, 0x30, 0x8e, - 0x4c, 0x42, 0xea, 0x2a, 0x5d, 0x6d, 0x28, 0x4d, 0xfd, 0x11, 0xe9, 0x59, 0xe1, 0x48, 0x22, 0xe7, - 0xc4, 0x37, 0x41, 0xb9, 0xc2, 0x91, 0x44, 0xff, 0x26, 0x72, 0x64, 0xaa, 0xde, 0x0a, 0x27, 0x7a, - 0x2e, 0xec, 0x2a, 0x0b, 0x61, 0x17, 0x24, 0x6b, 0xf3, 0x5f, 0xb1, 0xf6, 0xcb, 0x02, 0xd4, 0x93, - 0x52, 0x8d, 0x05, 0xc3, 0x1f, 0x89, 0x50, 0xfb, 0x63, 0x5f, 0x28, 0x6b, 0x38, 0xc7, 0x61, 0xf7, - 0xa0, 0xe2, 0x6a, 0xad, 0x92, 0x63, 0xf8, 0xed, 0x7c, 0x9d, 0xdf, 0xda, 0x45, 0x49, 0x2f, 0xd4, - 0x6a, 0xc6, 0x0d, 0x6a, 0xf5, 0x63, 0x80, 0x8c, 0x89, 0xbe, 0x9e, 0x89, 0x99, 0xd5, 0x8a, 0x24, - 0xbb, 0x01, 0x95, 0xcf, 0xdd, 0x60, 0x9a, 0x64, 0xa4, 0xf9, 0x78, 0x50, 0xfc, 0xb8, 0xe0, 0xfc, - 0xa1, 0x08, 0x35, 0x5b, 0xf7, 0xd9, 0x5d, 0xa8, 0x51, 0xdd, 0xb7, 0x1e, 0x5d, 0x9d, 0x7e, 0x09, - 0x84, 0x6d, 0xa7, 0x0d, 0x4d, 0xce, 0x47, 0xab, 0xca, 0x34, 0x36, 0xd6, 0xc7, 0xac, 0xbd, 0x29, - 0x8d, 0xc4, 0xd8, 0x76, 0x2e, 0x2d, 0xea, 0x13, 0xc4, 0xd8, 0x0f, 0x7d, 0x5c, 0x1f, 0x8e, 0x22, - 0x76, 0x37, 0x99, 0x75, 0x99, 0x34, 0xbe, 0x95, 0xd7, 0x78, 0x79, 0xd2, 0x7d, 0x68, 0xe6, 0xcc, - 0x5c, 0x31, 0xeb, 0xf7, 0xf3, 0xb3, 0xb6, 0x26, 0x49, 0x9d, 0x69, 0xbb, 0xb2, 0x55, 0xf8, 0x37, - 0xd6, 0xef, 0x23, 0x80, 0x4c, 0xe5, 0xf7, 0x3f, 0xbe, 0x9c, 0xdf, 0x97, 0x00, 0x06, 0x11, 0x56, - 0xb1, 0x91, 0x4b, 0x75, 0x77, 0xd9, 0x3f, 0x09, 0xa5, 0x12, 0x2f, 0x28, 0xcd, 0x69, 0x7c, 0x9d, - 0x37, 0x0d, 0x8f, 0x32, 0x86, 0xed, 0x42, 0x73, 0x24, 0x62, 0x4f, 0xf9, 0x14, 0x50, 0x76, 0xd1, - 0x6f, 0xe1, 0x9c, 0x32, 0x3d, 0x5b, 0xdd, 0x0c, 0x61, 0xd6, 0x2a, 0x3f, 0x86, 0xed, 0xc0, 0xb2, - 0xb8, 0x88, 0xa4, 0xd2, 0xd6, 0x8a, 0x69, 0x0f, 0xaf, 0x99, 0x46, 0x13, 0xf9, 0x64, 0x89, 0x37, - 0x45, 0xf6, 0xc1, 0x5c, 0x28, 0x7b, 0x6e, 0x14, 0xdb, 0xa2, 0xdc, 0x59, 0xb0, 0xb7, 0xef, 0x46, - 0x66, 0xd1, 0xf6, 0x3e, 0xc4, 0xb9, 0xfe, 0xfc, 0x2f, 0xb7, 0xee, 0xe4, 0x3a, 0x99, 0x89, 0x3c, - 0x9e, 0x6d, 0x53, 0xbc, 0x9c, 0xf9, 0x7a, 0x7b, 0xaa, 0xfd, 0x60, 0xdb, 0x8d, 0x7c, 0x54, 0x87, - 0x03, 0xfb, 0x5d, 0x4e, 0xaa, 0xd9, 0xc7, 0xd0, 0x8a, 0x94, 0x3c, 0x51, 0x22, 0x8e, 0x5f, 0x50, - 0x5d, 0xb3, 0xfd, 0xe6, 0x1b, 0xb6, 0xfe, 0x92, 0xe4, 0x13, 0x14, 0xf0, 0x95, 0x28, 0xff, 0xb9, - 0xfa, 0x43, 0x68, 0x2f, 0xce, 0xf8, 0x75, 0x76, 0x6f, 0xf5, 0x3e, 0x34, 0xd2, 0x19, 0xbc, 0x6a, - 0x60, 0x3d, 0xbf, 0xed, 0xbf, 0x2b, 0x40, 0xd5, 0xe4, 0x23, 0xbb, 0x0f, 0x8d, 0x40, 0x7a, 0x2e, - 0x3a, 0x90, 0xf4, 0xf6, 0xef, 0x64, 0xe9, 0xba, 0xf5, 0x38, 0x91, 0x99, 0xfd, 0xc8, 0xb0, 0x18, - 0x9e, 0x7e, 0x38, 0x96, 0x49, 0xfe, 0xb4, 0xb2, 0x41, 0xfd, 0x70, 0x2c, 0xb9, 0x11, 0xae, 0x3e, - 0x82, 0xd6, 0xbc, 0x8a, 0x2b, 0xfc, 0x7c, 0x6f, 0x3e, 0xd0, 0xa9, 0x1a, 0xa4, 0x83, 0xf2, 0x6e, - 0xdf, 0x87, 0x46, 0xca, 0x67, 0x9b, 0x97, 0x1d, 0x5f, 0xce, 0x8f, 0xcc, 0xf9, 0xea, 0x04, 0x00, - 0x99, 0x6b, 0x78, 0xcc, 0xe1, 0x25, 0x22, 0xcc, 0x9a, 0x87, 0xf4, 0x9b, 0x6a, 0xaf, 0xab, 0x5d, - 0x72, 0x65, 0x99, 0x13, 0xcd, 0xb6, 0x00, 0x46, 0x69, 0xaa, 0x7f, 0xc7, 0x01, 0x90, 0x43, 0x38, - 0x03, 0xa8, 0x27, 0x4e, 0xb0, 0x75, 0x68, 0xc6, 0xd6, 0x32, 0xf6, 0xba, 0x68, 0xae, 0xc2, 0xf3, - 0x2c, 0xec, 0x59, 0x95, 0x1b, 0x9e, 0x88, 0xb9, 0x9e, 0x95, 0x23, 0x87, 0x5b, 0x81, 0xf3, 0x19, - 0x54, 0x88, 0x81, 0x09, 0x1a, 0x6b, 0x57, 0x69, 0xdb, 0xfe, 0x9a, 0x0e, 0x4f, 0xc6, 0x64, 0x76, - 0xaf, 0x8c, 0x21, 0xcc, 0x0d, 0x80, 0xbd, 0x8f, 0x7d, 0xe4, 0xc8, 0xae, 0xe8, 0x55, 0x38, 0x14, - 0x3b, 0x3f, 0x80, 0x7a, 0xc2, 0xc6, 0x99, 0x3f, 0xf6, 0x43, 0x61, 0x5d, 0x24, 0x1a, 0xaf, 0x0d, - 0xfb, 0xa7, 0xae, 0x72, 0x3d, 0x2d, 0x4c, 0x9b, 0x52, 0xe1, 0x19, 0xc3, 0x79, 0x0f, 0x9a, 0xb9, - 0xbc, 0xc3, 0x70, 0x7b, 0x4e, 0xdb, 0x68, 0xb2, 0xdf, 0x7c, 0x38, 0x9f, 0xc0, 0xca, 0x5c, 0x0e, - 0x60, 0xb1, 0xf2, 0x47, 0x49, 0xb1, 0x32, 0x85, 0xe8, 0x52, 0xb7, 0xc5, 0xa0, 0x7c, 0x2e, 0xdc, - 0x33, 0xdb, 0x69, 0x11, 0xed, 0xfc, 0x16, 0x6f, 0x47, 0x49, 0x0f, 0xfb, 0xbf, 0x00, 0xa7, 0x5a, - 0x47, 0x2f, 0xa8, 0xa9, 0xb5, 0xca, 0x1a, 0xc8, 0x21, 0x04, 0xbb, 0x05, 0x4d, 0xfc, 0x88, 0xad, - 0xdc, 0xa8, 0xa6, 0x11, 0xb1, 0x01, 0xfc, 0x0f, 0x34, 0xc6, 0xe9, 0xf0, 0x92, 0x8d, 0x81, 0x64, - 0xf4, 0x3b, 0x50, 0x0f, 0xa5, 0x95, 0x99, 0x1e, 0xbb, 0x16, 0xca, 0x74, 0x9c, 0x1b, 0x04, 0x56, - 0x56, 0x31, 0xe3, 0xdc, 0x20, 0x20, 0xa1, 0x73, 0x07, 0xde, 0xb8, 0x74, 0xcf, 0x63, 0x6f, 0x41, - 0x75, 0xec, 0x07, 0x9a, 0x8a, 0x12, 0xf6, 0xf4, 0xf6, 0xcb, 0xf9, 0x47, 0x01, 0x20, 0x8b, 0x1f, - 0xcc, 0x0a, 0xac, 0x2e, 0x88, 0x59, 0x36, 0xd5, 0x24, 0x80, 0xfa, 0xc4, 0x9e, 0x53, 0x36, 0x32, - 0x6e, 0xce, 0xc7, 0xdc, 0x56, 0x72, 0x8c, 0x99, 0x13, 0x6c, 0xc7, 0x9e, 0x60, 0xaf, 0x73, 0x17, - 0x4b, 0x2d, 0x50, 0xa3, 0x95, 0xbf, 0x9a, 0x43, 0x96, 0xce, 0xdc, 0x4a, 0x56, 0x1f, 0xc1, 0xca, - 0x9c, 0xc9, 0xef, 0x59, 0xb3, 0xb2, 0xf3, 0x36, 0x9f, 0xcb, 0x3b, 0x50, 0x35, 0x77, 0x7a, 0xb6, - 0x01, 0x35, 0xd7, 0x33, 0x69, 0x9c, 0x3b, 0x4a, 0x50, 0xb8, 0x4b, 0x6c, 0x9e, 0x88, 0x9d, 0x3f, - 0x15, 0x01, 0x32, 0xfe, 0x6b, 0x74, 0xdb, 0x0f, 0xa0, 0x15, 0x0b, 0x4f, 0x86, 0x23, 0x57, 0xcd, - 0x48, 0x6a, 0x2f, 0x9d, 0x57, 0x0d, 0x59, 0x40, 0xe6, 0x3a, 0xef, 0xd2, 0xab, 0x3b, 0xef, 0x0d, - 0x28, 0x7b, 0x32, 0x9a, 0xd9, 0xd2, 0xc4, 0xe6, 0x27, 0xb2, 0x2f, 0xa3, 0xd9, 0xc1, 0x12, 0x27, - 0x04, 0xdb, 0x82, 0xea, 0xe4, 0x8c, 0x5e, 0x39, 0xcc, 0x6d, 0xed, 0xc6, 0x3c, 0xf6, 0xc9, 0x19, - 0xd2, 0x07, 0x4b, 0xdc, 0xa2, 0xd8, 0x1d, 0xa8, 0x4c, 0xce, 0x46, 0xbe, 0xb2, 0xc5, 0xe5, 0xfa, - 0x22, 0xbc, 0xeb, 0x2b, 0x7a, 0xd4, 0x40, 0x0c, 0x73, 0xa0, 0xa8, 0x26, 0xf6, 0x49, 0xa3, 0xbd, - 0xb0, 0x9a, 0x93, 0x83, 0x25, 0x5e, 0x54, 0x93, 0xbd, 0x3a, 0x54, 0xcd, 0xba, 0x3a, 0x7f, 0x2f, - 0x41, 0x6b, 0xde, 0x4b, 0xdc, 0xd9, 0x58, 0x79, 0xc9, 0xce, 0xc6, 0xca, 0x4b, 0x2f, 0x25, 0xc5, - 0xdc, 0xa5, 0xc4, 0x81, 0x8a, 0x3c, 0x0f, 0x85, 0xca, 0x3f, 0xe7, 0xec, 0x9f, 0xca, 0xf3, 0x10, - 0x1b, 0x63, 0x23, 0x9a, 0xeb, 0x33, 0x2b, 0xb6, 0xcf, 0x7c, 0x1f, 0x56, 0xc6, 0x32, 0x08, 0xe4, - 0xf9, 0x70, 0x36, 0x09, 0xfc, 0xf0, 0xcc, 0x36, 0x9b, 0xf3, 0x4c, 0xb6, 0x01, 0xd7, 0x46, 0xbe, - 0x42, 0x77, 0xf6, 0x65, 0xa8, 0x45, 0x48, 0x97, 0x55, 0xc4, 0x2d, 0xb2, 0xd9, 0xa7, 0xb0, 0xee, - 0x6a, 0x2d, 0x26, 0x91, 0x7e, 0x16, 0x46, 0xae, 0x77, 0xd6, 0x95, 0x1e, 0x65, 0xe1, 0x24, 0x72, - 0xb5, 0x7f, 0xec, 0x07, 0x78, 0x89, 0xaf, 0xd1, 0xd0, 0x57, 0xe2, 0xd8, 0x07, 0xd0, 0xf2, 0x94, - 0x70, 0xb5, 0xe8, 0x8a, 0x58, 0x1f, 0xb9, 0xfa, 0xb4, 0x53, 0xa7, 0x91, 0x0b, 0x5c, 0x9c, 0x83, - 0x8b, 0xde, 0x7e, 0xe6, 0x07, 0x23, 0x0f, 0xaf, 0x97, 0x0d, 0x33, 0x87, 0x39, 0x26, 0xdb, 0x02, - 0x46, 0x8c, 0xde, 0x24, 0xd2, 0xb3, 0x14, 0x0a, 0x04, 0xbd, 0x42, 0x82, 0x07, 0xae, 0xf6, 0x27, - 0x22, 0xd6, 0xee, 0x24, 0xa2, 0xf7, 0xa3, 0x12, 0xcf, 0x18, 0xec, 0x36, 0xb4, 0xfd, 0xd0, 0x0b, - 0xa6, 0x23, 0xf1, 0x22, 0xc2, 0x89, 0xa8, 0x30, 0xee, 0x2c, 0xd3, 0xa9, 0x72, 0xcd, 0xf2, 0x8f, - 0x2c, 0x1b, 0xa1, 0xe2, 0x62, 0x01, 0xba, 0x62, 0xa0, 0x96, 0x9f, 0x40, 0x9d, 0x2f, 0x0a, 0xd0, - 0x5e, 0x0c, 0x3c, 0xdc, 0xb6, 0x08, 0x27, 0x6f, 0x2f, 0xd7, 0x48, 0xa7, 0x5b, 0x59, 0xcc, 0x6d, - 0x65, 0x52, 0x2f, 0x4b, 0xb9, 0x7a, 0x99, 0x86, 0x45, 0xf9, 0xbb, 0xc3, 0x62, 0x6e, 0xa2, 0x95, - 0x85, 0x89, 0x3a, 0xbf, 0x29, 0xc0, 0xb5, 0x85, 0xe0, 0xfe, 0xde, 0x1e, 0xad, 0x43, 0x73, 0xe2, - 0x9e, 0x09, 0xf3, 0xb8, 0x10, 0xdb, 0x12, 0x92, 0x67, 0xfd, 0x07, 0xfc, 0x0b, 0x61, 0x39, 0x9f, - 0x51, 0x57, 0xfa, 0x96, 0x04, 0xc8, 0xa1, 0xd4, 0x0f, 0xe5, 0xd4, 0xd6, 0xe2, 0x24, 0x40, 0x12, - 0xe6, 0xe5, 0x30, 0x2a, 0x5d, 0x11, 0x46, 0xce, 0x21, 0xd4, 0x13, 0x07, 0xd9, 0x2d, 0xfb, 0xfa, - 0x53, 0xc8, 0x1e, 0x35, 0x9f, 0xc5, 0x42, 0xa1, 0xef, 0xe6, 0x29, 0xe8, 0x5d, 0xa8, 0x98, 0x36, - 0xb4, 0x78, 0x19, 0x61, 0x24, 0xce, 0x10, 0x6a, 0x96, 0xc3, 0x36, 0xa1, 0x7a, 0x3c, 0x4b, 0xdf, - 0x51, 0xec, 0x71, 0x81, 0xdf, 0x23, 0x8b, 0xc0, 0x33, 0xc8, 0x20, 0xd8, 0x0d, 0x28, 0x1f, 0xcf, - 0xfa, 0x5d, 0x73, 0xb1, 0xc4, 0x93, 0x0c, 0xbf, 0xf6, 0xaa, 0xc6, 0x21, 0xe7, 0x31, 0x2c, 0xe7, - 0xc7, 0xa5, 0x85, 0xbd, 0x90, 0x2b, 0xec, 0xe9, 0x91, 0x5d, 0x7c, 0xd5, 0x0d, 0xe3, 0x23, 0x00, - 0x7a, 0xab, 0x7d, 0xdd, 0x9b, 0xc9, 0xff, 0x43, 0xcd, 0xbe, 0xf1, 0xb2, 0x0f, 0x16, 0xde, 0xac, - 0x5b, 0xe9, 0x03, 0xf0, 0xdc, 0xc3, 0xb5, 0xf3, 0x00, 0x7b, 0xd4, 0x73, 0xa1, 0xba, 0xfe, 0x78, - 0xfc, 0xba, 0xe6, 0x1e, 0x40, 0xeb, 0x59, 0x14, 0xfd, 0x6b, 0x63, 0x7f, 0x02, 0x55, 0xf3, 0xd4, - 0x8c, 0x63, 0x02, 0xf4, 0xc0, 0xee, 0x01, 0x33, 0x7d, 0x6c, 0xde, 0x25, 0x6e, 0x00, 0x88, 0x9c, - 0xa2, 0x3d, 0xbb, 0xb9, 0x84, 0x9c, 0x77, 0x80, 0x1b, 0xc0, 0xe6, 0x06, 0xd4, 0xec, 0xab, 0x26, - 0x6b, 0x40, 0xe5, 0xd9, 0xe1, 0xb0, 0xf7, 0xb4, 0xbd, 0xc4, 0xea, 0x50, 0x3e, 0x18, 0x0c, 0x9f, - 0xb6, 0x0b, 0x48, 0x1d, 0x0e, 0x0e, 0x7b, 0xed, 0xe2, 0xe6, 0x6d, 0x58, 0xce, 0xbf, 0x6b, 0xb2, - 0x26, 0xd4, 0x86, 0xbb, 0x87, 0xdd, 0xbd, 0xc1, 0x8f, 0xdb, 0x4b, 0x6c, 0x19, 0xea, 0xfd, 0xc3, - 0x61, 0x6f, 0xff, 0x19, 0xef, 0xb5, 0x0b, 0x9b, 0x3f, 0x82, 0x46, 0xfa, 0x50, 0x84, 0x1a, 0xf6, - 0xfa, 0x87, 0xdd, 0xf6, 0x12, 0x03, 0xa8, 0x0e, 0x7b, 0xfb, 0xbc, 0x87, 0x7a, 0x6b, 0x50, 0x1a, - 0x0e, 0x0f, 0xda, 0x45, 0xb4, 0xba, 0xbf, 0xbb, 0x7f, 0xd0, 0x6b, 0x97, 0x90, 0x7c, 0xfa, 0xe4, - 0xe8, 0xe1, 0xb0, 0x5d, 0xde, 0xfc, 0x08, 0xae, 0x2d, 0x3c, 0xa1, 0xd0, 0xe8, 0x83, 0x5d, 0xde, - 0x43, 0x4d, 0x4d, 0xa8, 0x1d, 0xf1, 0xfe, 0xf3, 0xdd, 0xa7, 0xbd, 0x76, 0x01, 0x05, 0x8f, 0x07, - 0xfb, 0x8f, 0x7a, 0xdd, 0x76, 0x71, 0xef, 0xe6, 0x97, 0x2f, 0xd7, 0x0a, 0x5f, 0xbd, 0x5c, 0x2b, - 0x7c, 0xfd, 0x72, 0xad, 0xf0, 0xd7, 0x97, 0x6b, 0x85, 0x2f, 0xbe, 0x5d, 0x5b, 0xfa, 0xea, 0xdb, - 0xb5, 0xa5, 0xaf, 0xbf, 0x5d, 0x5b, 0x3a, 0xae, 0xd2, 0x9f, 0x15, 0x1f, 0xfe, 0x33, 0x00, 0x00, - 0xff, 0xff, 0x92, 0xc4, 0x20, 0x2a, 0xec, 0x18, 0x00, 0x00, + // 2535 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, 0x14, 0x45, 0x25, 0x91, 0x8e, 0x18, 0xc7, 0xa2, 0xb0, + 0xb4, 0x9d, 0x1e, 0x0a, 0x18, 0x4f, 0x8f, 0x4b, 0xe9, 0x41, 0x8f, 0x6f, 0x1f, 0xf6, 0x2d, 0x23, + 0xb1, 0x87, 0x1e, 0x7a, 0x2f, 0x10, 0xa0, 0x40, 0xd1, 0x4b, 0xd1, 0x2f, 0xd1, 0x63, 0x7b, 0x0f, + 0xd0, 0x4b, 0x0e, 0x3d, 0x04, 0x3d, 0xa4, 0x85, 0x73, 0xe9, 0x87, 0x68, 0x81, 0x62, 0x66, 0xf7, + 0xfd, 0x21, 0xa5, 0xc0, 0x71, 0x5b, 0xf4, 0xc4, 0x79, 0x33, 0xbf, 0x9d, 0x99, 0xdd, 0x9d, 0xd9, + 0x99, 0x5d, 0x42, 0x43, 0x46, 0xf1, 0x56, 0xa4, 0xa4, 0x96, 0xac, 0x18, 0x1d, 0xaf, 0xde, 0x3b, + 0xf1, 0xf5, 0xe9, 0xf4, 0x78, 0xcb, 0x93, 0x93, 0xed, 0x13, 0x79, 0x22, 0xb7, 0x49, 0x74, 0x3c, + 0x1d, 0xd3, 0x17, 0x7d, 0x10, 0x65, 0x86, 0x38, 0xff, 0x28, 0x42, 0x71, 0x10, 0xb1, 0xb7, 0xa1, + 0xea, 0x87, 0xd1, 0x54, 0xc7, 0x9d, 0xc2, 0x7a, 0x69, 0xa3, 0xb9, 0xd3, 0xd8, 0x8a, 0x8e, 0xb7, + 0xfa, 0xc8, 0xe1, 0x56, 0xc0, 0xd6, 0xa1, 0x2c, 0x2e, 0x84, 0xd7, 0x29, 0xae, 0x17, 0x36, 0x9a, + 0x3b, 0x80, 0x80, 0xde, 0x85, 0xf0, 0x06, 0xd1, 0xc1, 0x12, 0x27, 0x09, 0x7b, 0x0f, 0xaa, 0xb1, + 0x9c, 0x2a, 0x4f, 0x74, 0x4a, 0x84, 0x59, 0x46, 0xcc, 0x90, 0x38, 0x84, 0xb2, 0x52, 0xd4, 0x34, + 0xf6, 0x03, 0xd1, 0x29, 0x67, 0x9a, 0x1e, 0xfa, 0x81, 0xc1, 0x90, 0x84, 0xbd, 0x03, 0x95, 0xe3, + 0xa9, 0x1f, 0x8c, 0x3a, 0x15, 0x82, 0x34, 0x11, 0xb2, 0x87, 0x0c, 0xc2, 0x18, 0x19, 0x82, 0x26, + 0x42, 0x9d, 0x88, 0x4e, 0x35, 0x03, 0x3d, 0x46, 0x86, 0x01, 0x91, 0x0c, 0x6d, 0x8d, 0xfc, 0xf1, + 0xb8, 0x53, 0xcb, 0x6c, 0x75, 0xfd, 0xf1, 0xd8, 0xd8, 0x42, 0x09, 0xdb, 0x80, 0x7a, 0x14, 0xb8, + 0x7a, 0x2c, 0xd5, 0xa4, 0x03, 0x99, 0xdf, 0x47, 0x96, 0xc7, 0x53, 0x29, 0xbb, 0x0f, 0x4d, 0x4f, + 0x86, 0xb1, 0x56, 0xae, 0x1f, 0xea, 0xb8, 0xd3, 0x24, 0xf0, 0xeb, 0x08, 0xfe, 0x54, 0xaa, 0x33, + 0xa1, 0xf6, 0x33, 0x21, 0xcf, 0x23, 0xf7, 0xca, 0x50, 0x94, 0x91, 0xf3, 0x9b, 0x02, 0xd4, 0x13, + 0xad, 0xcc, 0x81, 0xe5, 0x5d, 0xe5, 0x9d, 0xfa, 0x5a, 0x78, 0x7a, 0xaa, 0x44, 0xa7, 0xb0, 0x5e, + 0xd8, 0x68, 0xf0, 0x39, 0x1e, 0x6b, 0x41, 0x71, 0x30, 0xa4, 0xf5, 0x6e, 0xf0, 0xe2, 0x60, 0xc8, + 0x3a, 0x50, 0x7b, 0xe6, 0x2a, 0xdf, 0x0d, 0x35, 0x2d, 0x70, 0x83, 0x27, 0x9f, 0xec, 0x26, 0x34, + 0x06, 0xc3, 0x67, 0x42, 0xc5, 0xbe, 0x0c, 0x69, 0x59, 0x1b, 0x3c, 0x63, 0xb0, 0x35, 0x80, 0xc1, + 0xf0, 0xa1, 0x70, 0x51, 0x69, 0xdc, 0xa9, 0xac, 0x97, 0x36, 0x1a, 0x3c, 0xc7, 0x71, 0x7e, 0x01, + 0x15, 0xda, 0x6a, 0xf6, 0x31, 0x54, 0x47, 0xfe, 0x89, 0x88, 0xb5, 0x71, 0x67, 0x6f, 0xe7, 0x8b, + 0xaf, 0x6f, 0x2d, 0xfd, 0xf5, 0xeb, 0x5b, 0x9b, 0xb9, 0x98, 0x92, 0x91, 0x08, 0x3d, 0x19, 0x6a, + 0xd7, 0x0f, 0x85, 0x8a, 0xb7, 0x4f, 0xe4, 0x3d, 0x33, 0x64, 0xab, 0x4b, 0x3f, 0xdc, 0x6a, 0x60, + 0xb7, 0xa1, 0xe2, 0x87, 0x23, 0x71, 0x41, 0xfe, 0x97, 0xf6, 0xae, 0x5b, 0x55, 0xcd, 0xc1, 0x54, + 0x47, 0x53, 0xdd, 0x47, 0x11, 0x37, 0x08, 0xe7, 0xcf, 0x05, 0xa8, 0x9a, 0x50, 0x62, 0x37, 0xa1, + 0x3c, 0x11, 0xda, 0x25, 0xfb, 0xcd, 0x9d, 0xba, 0xd9, 0x52, 0xed, 0x72, 0xe2, 0x62, 0x94, 0x4e, + 0xe4, 0x14, 0xd7, 0xbe, 0x98, 0x45, 0xe9, 0x63, 0xe4, 0x70, 0x2b, 0x60, 0x3f, 0x80, 0x5a, 0x28, + 0xf4, 0xb9, 0x54, 0x67, 0xb4, 0x46, 0x2d, 0x13, 0x16, 0x87, 0x42, 0x3f, 0x96, 0x23, 0xc1, 0x13, + 0x19, 0xbb, 0x0b, 0xf5, 0x58, 0x78, 0x53, 0xe5, 0xeb, 0x19, 0xad, 0x57, 0x6b, 0xa7, 0x4d, 0xc1, + 0x6a, 0x79, 0x04, 0x4e, 0x11, 0xec, 0x0e, 0x34, 0x62, 0xe1, 0x29, 0xa1, 0x45, 0xf8, 0x19, 0xad, + 0x5f, 0x73, 0x67, 0xc5, 0xc2, 0x95, 0xd0, 0xbd, 0xf0, 0x33, 0x9e, 0xc9, 0x9d, 0x5f, 0x15, 0xa1, + 0x8c, 0x3e, 0x33, 0x06, 0x65, 0x57, 0x9d, 0x98, 0x8c, 0x6a, 0x70, 0xa2, 0x59, 0x1b, 0x4a, 0xa8, + 0xa3, 0x48, 0x2c, 0x24, 0x91, 0xe3, 0x9d, 0x8f, 0xec, 0x86, 0x22, 0x89, 0xe3, 0xa6, 0xb1, 0x50, + 0x76, 0x1f, 0x89, 0x66, 0xb7, 0xa1, 0x11, 0x29, 0x79, 0x31, 0x7b, 0x6e, 0x3c, 0xc8, 0xa2, 0x14, + 0x99, 0xe8, 0x40, 0x3d, 0xb2, 0x14, 0xdb, 0x04, 0x10, 0x17, 0x5a, 0xb9, 0x07, 0x32, 0xd6, 0x71, + 0xa7, 0x4a, 0xde, 0x52, 0xdc, 0x23, 0xa3, 0x7f, 0xc4, 0x73, 0x52, 0xb6, 0x0a, 0xf5, 0x53, 0x19, + 0xeb, 0xd0, 0x9d, 0x08, 0xca, 0x90, 0x06, 0x4f, 0xbf, 0x99, 0x03, 0xd5, 0x69, 0xe0, 0x4f, 0x7c, + 0xdd, 0x69, 0x64, 0x3a, 0x9e, 0x12, 0x87, 0x5b, 0x09, 0x46, 0xb1, 0x77, 0xa2, 0xe4, 0x34, 0x3a, + 0x72, 0x95, 0x08, 0x35, 0xe5, 0x4f, 0x83, 0xcf, 0xf1, 0x9c, 0xbb, 0x50, 0x35, 0x96, 0x71, 0x62, + 0x48, 0xd9, 0x58, 0x27, 0x1a, 0x63, 0xbc, 0x7f, 0x94, 0xc4, 0x78, 0xff, 0xc8, 0xe9, 0x42, 0xd5, + 0xd8, 0x40, 0xf4, 0x21, 0xfa, 0x65, 0xd1, 0x48, 0x23, 0x6f, 0x28, 0xc7, 0xda, 0xc4, 0x14, 0x27, + 0x9a, 0xb4, 0xba, 0xca, 0xac, 0x60, 0x89, 0x13, 0xed, 0x3c, 0x82, 0x46, 0xba, 0x37, 0x64, 0xa2, + 0x6b, 0xd5, 0x14, 0xfb, 0x5d, 0x1c, 0x40, 0x13, 0x36, 0x46, 0x89, 0xc6, 0x85, 0x90, 0x91, 0xf6, + 0x65, 0xe8, 0x06, 0xa4, 0xa8, 0xce, 0xd3, 0x6f, 0xe7, 0xb7, 0x25, 0xa8, 0x50, 0x90, 0xb1, 0x0d, + 0x8c, 0xe9, 0x68, 0x6a, 0x66, 0x50, 0xda, 0x63, 0x36, 0xa6, 0x81, 0xb2, 0x27, 0x0d, 0x69, 0xcc, + 0xa4, 0x55, 0x8c, 0xaf, 0x40, 0x78, 0x5a, 0x2a, 0x6b, 0x27, 0xfd, 0x46, 0xfb, 0x23, 0xcc, 0x31, + 0xb3, 0xe5, 0x44, 0xb3, 0x3b, 0x50, 0x95, 0x94, 0x18, 0xb4, 0xeb, 0xdf, 0x92, 0x2e, 0x16, 0x82, + 0xca, 0x95, 0x70, 0x47, 0x32, 0x0c, 0x66, 0x14, 0x0b, 0x75, 0x9e, 0x7e, 0x63, 0xa8, 0x52, 0x26, + 0x3c, 0x99, 0x45, 0xe6, 0x60, 0x6c, 0x99, 0x50, 0x7d, 0x9c, 0x30, 0x79, 0x26, 0xc7, 0xa3, 0xef, + 0xc9, 0x24, 0x1a, 0xc7, 0x83, 0x48, 0x77, 0xae, 0x67, 0x41, 0x95, 0xf0, 0x78, 0x2a, 0x45, 0xa4, + 0xe7, 0x7a, 0xa7, 0x02, 0x91, 0x37, 0x32, 0xe4, 0xbe, 0xe5, 0xf1, 0x54, 0x9a, 0xe5, 0x0a, 0x42, + 0x5f, 0x27, 0x68, 0x2e, 0x57, 0x10, 0x9b, 0xc9, 0x31, 0xc6, 0x86, 0xc3, 0x03, 0x44, 0xbe, 0x91, + 0x9d, 0xcf, 0x86, 0xc3, 0xad, 0xc4, 0xcc, 0x36, 0x9e, 0x06, 0xba, 0xdf, 0xed, 0xbc, 0x69, 0x96, + 0x32, 0xf9, 0x76, 0xd6, 0xb2, 0x09, 0xe0, 0xb2, 0xc6, 0xfe, 0xcf, 0x4d, 0xbc, 0x94, 0x38, 0xd1, + 0x4e, 0x1f, 0xea, 0x89, 0x8b, 0x97, 0xc2, 0xe0, 0x1e, 0xd4, 0xe2, 0x53, 0x57, 0xf9, 0xe1, 0x09, + 0xed, 0x50, 0x6b, 0xe7, 0x7a, 0x3a, 0xa3, 0xa1, 0xe1, 0xa3, 0x17, 0x09, 0xc6, 0x91, 0x49, 0x48, + 0x5d, 0xa5, 0xab, 0x0d, 0xa5, 0xa9, 0x3f, 0x22, 0x3d, 0x2b, 0x1c, 0x49, 0xe4, 0x9c, 0xf8, 0x26, + 0x28, 0x57, 0x38, 0x92, 0xe8, 0xdf, 0x44, 0x8e, 0x4c, 0xd5, 0x5b, 0xe1, 0x44, 0xcf, 0x85, 0x5d, + 0x65, 0x21, 0xec, 0x82, 0x64, 0x6d, 0xfe, 0x2f, 0xd6, 0x7e, 0x5d, 0x80, 0x7a, 0x52, 0xaa, 0xb1, + 0x60, 0xf8, 0x23, 0x11, 0x6a, 0x7f, 0xec, 0x0b, 0x65, 0x0d, 0xe7, 0x38, 0xec, 0x1e, 0x54, 0x5c, + 0xad, 0x55, 0x72, 0x0c, 0xbf, 0x99, 0xaf, 0xf3, 0x5b, 0xbb, 0x28, 0xe9, 0x85, 0x5a, 0xcd, 0xb8, + 0x41, 0xad, 0x7e, 0x08, 0x90, 0x31, 0xd1, 0xd7, 0x33, 0x31, 0xb3, 0x5a, 0x91, 0x64, 0x37, 0xa0, + 0xf2, 0x99, 0x1b, 0x4c, 0x93, 0x8c, 0x34, 0x1f, 0x0f, 0x8a, 0x1f, 0x16, 0x9c, 0x3f, 0x15, 0xa1, + 0x66, 0xeb, 0x3e, 0xbb, 0x0b, 0x35, 0xaa, 0xfb, 0xd6, 0xa3, 0xab, 0xd3, 0x2f, 0x81, 0xb0, 0xed, + 0xb4, 0xa1, 0xc9, 0xf9, 0x68, 0x55, 0x99, 0xc6, 0xc6, 0xfa, 0x98, 0xb5, 0x37, 0xa5, 0x91, 0x18, + 0xdb, 0xce, 0xa5, 0x45, 0x7d, 0x82, 0x18, 0xfb, 0xa1, 0x8f, 0xeb, 0xc3, 0x51, 0xc4, 0xee, 0x26, + 0xb3, 0x2e, 0x93, 0xc6, 0x37, 0xf2, 0x1a, 0x2f, 0x4f, 0xba, 0x0f, 0xcd, 0x9c, 0x99, 0x2b, 0x66, + 0xfd, 0x6e, 0x7e, 0xd6, 0xd6, 0x24, 0xa9, 0x33, 0x6d, 0x57, 0xb6, 0x0a, 0xff, 0xc5, 0xfa, 0x7d, + 0x00, 0x90, 0xa9, 0xfc, 0xee, 0xc7, 0x97, 0xf3, 0xc7, 0x12, 0xc0, 0x20, 0xc2, 0x2a, 0x36, 0x72, + 0xa9, 0xee, 0x2e, 0xfb, 0x27, 0xa1, 0x54, 0xe2, 0x39, 0xa5, 0x39, 0x8d, 0xaf, 0xf3, 0xa6, 0xe1, + 0x51, 0xc6, 0xb0, 0x5d, 0x68, 0x8e, 0x44, 0xec, 0x29, 0x9f, 0x02, 0xca, 0x2e, 0xfa, 0x2d, 0x9c, + 0x53, 0xa6, 0x67, 0xab, 0x9b, 0x21, 0xcc, 0x5a, 0xe5, 0xc7, 0xb0, 0x1d, 0x58, 0x16, 0x17, 0x91, + 0x54, 0xda, 0x5a, 0x31, 0xed, 0xe1, 0x35, 0xd3, 0x68, 0x22, 0x9f, 0x2c, 0xf1, 0xa6, 0xc8, 0x3e, + 0x98, 0x0b, 0x65, 0xcf, 0x8d, 0x62, 0x5b, 0x94, 0x3b, 0x0b, 0xf6, 0xf6, 0xdd, 0xc8, 0x2c, 0xda, + 0xde, 0xfb, 0x38, 0xd7, 0x5f, 0xfe, 0xed, 0xd6, 0x9d, 0x5c, 0x27, 0x33, 0x91, 0xc7, 0xb3, 0x6d, + 0x8a, 0x97, 0x33, 0x5f, 0x6f, 0x4f, 0xb5, 0x1f, 0x6c, 0xbb, 0x91, 0x8f, 0xea, 0x70, 0x60, 0xbf, + 0xcb, 0x49, 0x35, 0xfb, 0x10, 0x5a, 0x91, 0x92, 0x27, 0x4a, 0xc4, 0xf1, 0x73, 0xaa, 0x6b, 0xb6, + 0xdf, 0x7c, 0xcd, 0xd6, 0x5f, 0x92, 0x7c, 0x84, 0x02, 0xbe, 0x12, 0xe5, 0x3f, 0x57, 0x7f, 0x0c, + 0xed, 0xc5, 0x19, 0xbf, 0xca, 0xee, 0xad, 0xde, 0x87, 0x46, 0x3a, 0x83, 0x97, 0x0d, 0xac, 0xe7, + 0xb7, 0xfd, 0x0f, 0x05, 0xa8, 0x9a, 0x7c, 0x64, 0xf7, 0xa1, 0x11, 0x48, 0xcf, 0x45, 0x07, 0x92, + 0xde, 0xfe, 0xad, 0x2c, 0x5d, 0xb7, 0x3e, 0x49, 0x64, 0x66, 0x3f, 0x32, 0x2c, 0x86, 0xa7, 0x1f, + 0x8e, 0x65, 0x92, 0x3f, 0xad, 0x6c, 0x50, 0x3f, 0x1c, 0x4b, 0x6e, 0x84, 0xab, 0x8f, 0xa0, 0x35, + 0xaf, 0xe2, 0x0a, 0x3f, 0xdf, 0x99, 0x0f, 0x74, 0xaa, 0x06, 0xe9, 0xa0, 0xbc, 0xdb, 0xf7, 0xa1, + 0x91, 0xf2, 0xd9, 0xe6, 0x65, 0xc7, 0x97, 0xf3, 0x23, 0x73, 0xbe, 0x3a, 0x01, 0x40, 0xe6, 0x1a, + 0x1e, 0x73, 0x78, 0x89, 0x08, 0xb3, 0xe6, 0x21, 0xfd, 0xa6, 0xda, 0xeb, 0x6a, 0x97, 0x5c, 0x59, + 0xe6, 0x44, 0xb3, 0x2d, 0x80, 0x51, 0x9a, 0xea, 0xdf, 0x72, 0x00, 0xe4, 0x10, 0xce, 0x00, 0xea, + 0x89, 0x13, 0x6c, 0x1d, 0x9a, 0xb1, 0xb5, 0x8c, 0xbd, 0x2e, 0x9a, 0xab, 0xf0, 0x3c, 0x0b, 0x7b, + 0x56, 0xe5, 0x86, 0x27, 0x62, 0xae, 0x67, 0xe5, 0xc8, 0xe1, 0x56, 0xe0, 0x7c, 0x0a, 0x15, 0x62, + 0x60, 0x82, 0xc6, 0xda, 0x55, 0xda, 0xb6, 0xbf, 0xa6, 0xc3, 0x93, 0x31, 0x99, 0xdd, 0x2b, 0x63, + 0x08, 0x73, 0x03, 0x60, 0xef, 0x62, 0x1f, 0x39, 0xb2, 0x2b, 0x7a, 0x15, 0x0e, 0xc5, 0xce, 0x8f, + 0xa0, 0x9e, 0xb0, 0x71, 0xe6, 0x81, 0x1f, 0x0a, 0xeb, 0x22, 0xd1, 0x78, 0x6d, 0xf0, 0x4e, 0x5d, + 0xe5, 0x7a, 0x5a, 0x98, 0x36, 0xa5, 0xc2, 0x33, 0x86, 0xf3, 0x0e, 0x34, 0x73, 0x79, 0x87, 0xe1, + 0xf6, 0x8c, 0xb6, 0xd1, 0x64, 0xbf, 0xf9, 0x70, 0x3e, 0x82, 0x95, 0xb9, 0x1c, 0xc0, 0x62, 0xe5, + 0x8f, 0x92, 0x62, 0x65, 0x0a, 0xd1, 0xa5, 0x6e, 0x8b, 0x41, 0xf9, 0x5c, 0xb8, 0x67, 0xb6, 0xd3, + 0x22, 0xda, 0xf9, 0x3d, 0xde, 0x8e, 0x92, 0x1e, 0xf6, 0xfb, 0x00, 0xa7, 0x5a, 0x47, 0xcf, 0xa9, + 0xa9, 0xb5, 0xca, 0x1a, 0xc8, 0x21, 0x04, 0xbb, 0x05, 0x4d, 0xfc, 0x88, 0xad, 0xdc, 0xa8, 0xa6, + 0x11, 0xb1, 0x01, 0x7c, 0x0f, 0x1a, 0xe3, 0x74, 0x78, 0xc9, 0xc6, 0x40, 0x32, 0xfa, 0x2d, 0xa8, + 0x87, 0xd2, 0xca, 0x4c, 0x8f, 0x5d, 0x0b, 0x65, 0x3a, 0xce, 0x0d, 0x02, 0x2b, 0xab, 0x98, 0x71, + 0x6e, 0x10, 0x90, 0xd0, 0xb9, 0x03, 0xaf, 0x5d, 0xba, 0xe7, 0xb1, 0x37, 0xa0, 0x3a, 0xf6, 0x03, + 0x4d, 0x45, 0x09, 0x7b, 0x7a, 0xfb, 0xe5, 0xfc, 0xab, 0x00, 0x90, 0xc5, 0x0f, 0x66, 0x05, 0x56, + 0x17, 0xc4, 0x2c, 0x9b, 0x6a, 0x12, 0x40, 0x7d, 0x62, 0xcf, 0x29, 0x1b, 0x19, 0x37, 0xe7, 0x63, + 0x6e, 0x2b, 0x39, 0xc6, 0xcc, 0x09, 0xb6, 0x63, 0x4f, 0xb0, 0x57, 0xb9, 0x8b, 0xa5, 0x16, 0xa8, + 0xd1, 0xca, 0x5f, 0xcd, 0x21, 0x4b, 0x67, 0x6e, 0x25, 0xab, 0x8f, 0x60, 0x65, 0xce, 0xe4, 0x77, + 0xac, 0x59, 0xd9, 0x79, 0x9b, 0xcf, 0xe5, 0x1d, 0xa8, 0x9a, 0x3b, 0x3d, 0xdb, 0x80, 0x9a, 0xeb, + 0x99, 0x34, 0xce, 0x1d, 0x25, 0x28, 0xdc, 0x25, 0x36, 0x4f, 0xc4, 0xce, 0x5f, 0x8a, 0x00, 0x19, + 0xff, 0x15, 0xba, 0xed, 0x07, 0xd0, 0x8a, 0x85, 0x27, 0xc3, 0x91, 0xab, 0x66, 0x24, 0xb5, 0x97, + 0xce, 0xab, 0x86, 0x2c, 0x20, 0x73, 0x9d, 0x77, 0xe9, 0xe5, 0x9d, 0xf7, 0x06, 0x94, 0x3d, 0x19, + 0xcd, 0x6c, 0x69, 0x62, 0xf3, 0x13, 0xd9, 0x97, 0xd1, 0xec, 0x60, 0x89, 0x13, 0x82, 0x6d, 0x41, + 0x75, 0x72, 0x46, 0xaf, 0x1c, 0xe6, 0xb6, 0x76, 0x63, 0x1e, 0xfb, 0xf8, 0x0c, 0xe9, 0x83, 0x25, + 0x6e, 0x51, 0xec, 0x0e, 0x54, 0x26, 0x67, 0x23, 0x5f, 0xd9, 0xe2, 0x72, 0x7d, 0x11, 0xde, 0xf5, + 0x15, 0x3d, 0x6a, 0x20, 0x86, 0x39, 0x50, 0x54, 0x13, 0xfb, 0xa4, 0xd1, 0x5e, 0x58, 0xcd, 0xc9, + 0xc1, 0x12, 0x2f, 0xaa, 0xc9, 0x5e, 0x1d, 0xaa, 0x66, 0x5d, 0x9d, 0x7f, 0x96, 0xa0, 0x35, 0xef, + 0x25, 0xee, 0x6c, 0xac, 0xbc, 0x64, 0x67, 0x63, 0xe5, 0xa5, 0x97, 0x92, 0x62, 0xee, 0x52, 0xe2, + 0x40, 0x45, 0x9e, 0x87, 0x42, 0xe5, 0x9f, 0x73, 0xf6, 0x4f, 0xe5, 0x79, 0x88, 0x8d, 0xb1, 0x11, + 0xcd, 0xf5, 0x99, 0x15, 0xdb, 0x67, 0xbe, 0x0b, 0x2b, 0x63, 0x19, 0x04, 0xf2, 0x7c, 0x38, 0x9b, + 0x04, 0x7e, 0x78, 0x66, 0x9b, 0xcd, 0x79, 0x26, 0xdb, 0x80, 0x6b, 0x23, 0x5f, 0xa1, 0x3b, 0xfb, + 0x32, 0xd4, 0x22, 0xa4, 0xcb, 0x2a, 0xe2, 0x16, 0xd9, 0xec, 0x63, 0x58, 0x77, 0xb5, 0x16, 0x93, + 0x48, 0x3f, 0x0d, 0x23, 0xd7, 0x3b, 0xeb, 0x4a, 0x8f, 0xb2, 0x70, 0x12, 0xb9, 0xda, 0x3f, 0xf6, + 0x03, 0xbc, 0xc4, 0xd7, 0x68, 0xe8, 0x4b, 0x71, 0xec, 0x3d, 0x68, 0x79, 0x4a, 0xb8, 0x5a, 0x74, + 0x45, 0xac, 0x8f, 0x5c, 0x7d, 0xda, 0xa9, 0xd3, 0xc8, 0x05, 0x2e, 0xce, 0xc1, 0x45, 0x6f, 0x3f, + 0xf5, 0x83, 0x91, 0x87, 0xd7, 0xcb, 0x86, 0x99, 0xc3, 0x1c, 0x93, 0x6d, 0x01, 0x23, 0x46, 0x6f, + 0x12, 0xe9, 0x59, 0x0a, 0x05, 0x82, 0x5e, 0x21, 0xc1, 0x03, 0x57, 0xfb, 0x13, 0x11, 0x6b, 0x77, + 0x12, 0xd1, 0xfb, 0x51, 0x89, 0x67, 0x0c, 0x76, 0x1b, 0xda, 0x7e, 0xe8, 0x05, 0xd3, 0x91, 0x78, + 0x1e, 0xe1, 0x44, 0x54, 0x18, 0x77, 0x96, 0xe9, 0x54, 0xb9, 0x66, 0xf9, 0x47, 0x96, 0x8d, 0x50, + 0x71, 0xb1, 0x00, 0x5d, 0x31, 0x50, 0xcb, 0x4f, 0xa0, 0xce, 0xe7, 0x05, 0x68, 0x2f, 0x06, 0x1e, + 0x6e, 0x5b, 0x84, 0x93, 0xb7, 0x97, 0x6b, 0xa4, 0xd3, 0xad, 0x2c, 0xe6, 0xb6, 0x32, 0xa9, 0x97, + 0xa5, 0x5c, 0xbd, 0x4c, 0xc3, 0xa2, 0xfc, 0xed, 0x61, 0x31, 0x37, 0xd1, 0xca, 0xc2, 0x44, 0x9d, + 0xdf, 0x15, 0xe0, 0xda, 0x42, 0x70, 0x7f, 0x67, 0x8f, 0xd6, 0xa1, 0x39, 0x71, 0xcf, 0x84, 0x79, + 0x5c, 0x88, 0x6d, 0x09, 0xc9, 0xb3, 0xfe, 0x07, 0xfe, 0x85, 0xb0, 0x9c, 0xcf, 0xa8, 0x2b, 0x7d, + 0x4b, 0x02, 0xe4, 0x50, 0xea, 0x87, 0x72, 0x6a, 0x6b, 0x71, 0x12, 0x20, 0x09, 0xf3, 0x72, 0x18, + 0x95, 0xae, 0x08, 0x23, 0xe7, 0x10, 0xea, 0x89, 0x83, 0xec, 0x96, 0x7d, 0xfd, 0x29, 0x64, 0x8f, + 0x9a, 0x4f, 0x63, 0xa1, 0xd0, 0x77, 0xf3, 0x14, 0xf4, 0x36, 0x54, 0x4c, 0x1b, 0x5a, 0xbc, 0x8c, + 0x30, 0x12, 0x67, 0x08, 0x35, 0xcb, 0x61, 0x9b, 0x50, 0x3d, 0x9e, 0xa5, 0xef, 0x28, 0xf6, 0xb8, + 0xc0, 0xef, 0x91, 0x45, 0xe0, 0x19, 0x64, 0x10, 0xec, 0x06, 0x94, 0x8f, 0x67, 0xfd, 0xae, 0xb9, + 0x58, 0xe2, 0x49, 0x86, 0x5f, 0x7b, 0x55, 0xe3, 0x90, 0xf3, 0x09, 0x2c, 0xe7, 0xc7, 0xa5, 0x85, + 0xbd, 0x90, 0x2b, 0xec, 0xe9, 0x91, 0x5d, 0x7c, 0xd9, 0x0d, 0xe3, 0x03, 0x00, 0x7a, 0xab, 0x7d, + 0xd5, 0x9b, 0xc9, 0x0f, 0xa1, 0x66, 0xdf, 0x78, 0xd9, 0x7b, 0x0b, 0x6f, 0xd6, 0xad, 0xf4, 0x01, + 0x78, 0xee, 0xe1, 0xda, 0x79, 0x80, 0x3d, 0xea, 0xb9, 0x50, 0x5d, 0x7f, 0x3c, 0x7e, 0x55, 0x73, + 0x0f, 0xa0, 0xf5, 0x34, 0x8a, 0xfe, 0xb3, 0xb1, 0x3f, 0x83, 0xaa, 0x79, 0x6a, 0xc6, 0x31, 0x01, + 0x7a, 0x60, 0xf7, 0x80, 0x99, 0x3e, 0x36, 0xef, 0x12, 0x37, 0x00, 0x44, 0x4e, 0xd1, 0x9e, 0xdd, + 0x5c, 0x42, 0xce, 0x3b, 0xc0, 0x0d, 0x60, 0x73, 0x03, 0x6a, 0xf6, 0x55, 0x93, 0x35, 0xa0, 0xf2, + 0xf4, 0x70, 0xd8, 0x7b, 0xd2, 0x5e, 0x62, 0x75, 0x28, 0x1f, 0x0c, 0x86, 0x4f, 0xda, 0x05, 0xa4, + 0x0e, 0x07, 0x87, 0xbd, 0x76, 0x71, 0xf3, 0x36, 0x2c, 0xe7, 0xdf, 0x35, 0x59, 0x13, 0x6a, 0xc3, + 0xdd, 0xc3, 0xee, 0xde, 0xe0, 0xa7, 0xed, 0x25, 0xb6, 0x0c, 0xf5, 0xfe, 0xe1, 0xb0, 0xb7, 0xff, + 0x94, 0xf7, 0xda, 0x85, 0xcd, 0x9f, 0x40, 0x23, 0x7d, 0x28, 0x42, 0x0d, 0x7b, 0xfd, 0xc3, 0x6e, + 0x7b, 0x89, 0x01, 0x54, 0x87, 0xbd, 0x7d, 0xde, 0x43, 0xbd, 0x35, 0x28, 0x0d, 0x87, 0x07, 0xed, + 0x22, 0x5a, 0xdd, 0xdf, 0xdd, 0x3f, 0xe8, 0xb5, 0x4b, 0x48, 0x3e, 0x79, 0x7c, 0xf4, 0x70, 0xd8, + 0x2e, 0x6f, 0x7e, 0x00, 0xd7, 0x16, 0x9e, 0x50, 0x68, 0xf4, 0xc1, 0x2e, 0xef, 0xa1, 0xa6, 0x26, + 0xd4, 0x8e, 0x78, 0xff, 0xd9, 0xee, 0x93, 0x5e, 0xbb, 0x80, 0x82, 0x4f, 0x06, 0xfb, 0x8f, 0x7a, + 0xdd, 0x76, 0x71, 0xef, 0xe6, 0x17, 0x2f, 0xd6, 0x0a, 0x5f, 0xbe, 0x58, 0x2b, 0x7c, 0xf5, 0x62, + 0xad, 0xf0, 0xf7, 0x17, 0x6b, 0x85, 0xcf, 0xbf, 0x59, 0x5b, 0xfa, 0xf2, 0x9b, 0xb5, 0xa5, 0xaf, + 0xbe, 0x59, 0x5b, 0x3a, 0xae, 0xd2, 0x9f, 0x15, 0xef, 0xff, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xd1, + 0x92, 0xe3, 0x09, 0xec, 0x18, 0x00, 0x00, } func (m *Op) Marshal() (dAtA []byte, err error) { diff --git a/solver/pb/ops.proto b/solver/pb/ops.proto index 09af4c0d7508..ca597a6d7dfb 100644 --- a/solver/pb/ops.proto +++ b/solver/pb/ops.proto @@ -243,8 +243,8 @@ message Range { // Position is single location in a source file message Position { - int32 Line = 1; - int32 Character = 2; + int32 line = 1; + int32 character = 2; } message ExportCache {