mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 18:13:42 +08:00 
			
		
		
		
	build: add experimental support for print flag
Print flag can be used to make additional information requests about the build and print their results. Currently Dockerfile supports: outline, targets, subrequests.describe Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
		
							
								
								
									
										81
									
								
								vendor/github.com/moby/buildkit/frontend/subrequests/describe.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								vendor/github.com/moby/buildkit/frontend/subrequests/describe.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
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"
 | 
			
		||||
	"github.com/moby/buildkit/solver/errdefs"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const RequestSubrequestsDescribe = "frontend.subrequests.describe"
 | 
			
		||||
 | 
			
		||||
var SubrequestsDescribeDefinition = Request{
 | 
			
		||||
	Name:        RequestSubrequestsDescribe,
 | 
			
		||||
	Version:     "1.0.0",
 | 
			
		||||
	Type:        TypeRPC,
 | 
			
		||||
	Description: "List available subrequest types",
 | 
			
		||||
	Metadata: []Named{
 | 
			
		||||
		{Name: "result.json"},
 | 
			
		||||
		{Name: "result.txt"},
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Describe(ctx context.Context, c client.Client) ([]Request, error) {
 | 
			
		||||
	gwcaps := c.BuildOpts().Caps
 | 
			
		||||
 | 
			
		||||
	if err := (&gwcaps).Supports(gwpb.CapFrontendCaps); err != nil {
 | 
			
		||||
		return nil, errdefs.NewUnsupportedSubrequestError(RequestSubrequestsDescribe)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res, err := c.Solve(ctx, client.SolveRequest{
 | 
			
		||||
		FrontendOpt: map[string]string{
 | 
			
		||||
			"requestid":     RequestSubrequestsDescribe,
 | 
			
		||||
			"frontend.caps": "moby.buildkit.frontend.subrequests",
 | 
			
		||||
		},
 | 
			
		||||
		Frontend: "dockerfile.v0",
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		var reqErr *errdefs.UnsupportedSubrequestError
 | 
			
		||||
		if errors.As(err, &reqErr) {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		var capErr *errdefs.UnsupportedFrontendCapError
 | 
			
		||||
		if errors.As(err, &capErr) {
 | 
			
		||||
			return nil, errdefs.NewUnsupportedSubrequestError(RequestSubrequestsDescribe)
 | 
			
		||||
		}
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dt, ok := res.Metadata["result.json"]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, errors.Errorf("no result.json metadata in response")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var reqs []Request
 | 
			
		||||
	if err := json.Unmarshal(dt, &reqs); err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "failed to parse describe result")
 | 
			
		||||
	}
 | 
			
		||||
	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()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										146
									
								
								vendor/github.com/moby/buildkit/frontend/subrequests/outline/outline.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								vendor/github.com/moby/buildkit/frontend/subrequests/outline/outline.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										84
									
								
								vendor/github.com/moby/buildkit/frontend/subrequests/targets/targets.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								vendor/github.com/moby/buildkit/frontend/subrequests/targets/targets.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -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()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								vendor/github.com/moby/buildkit/frontend/subrequests/types.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/moby/buildkit/frontend/subrequests/types.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
package subrequests
 | 
			
		||||
 | 
			
		||||
type Request struct {
 | 
			
		||||
	Name        string      `json:"name"`
 | 
			
		||||
	Version     string      `json:"version"`
 | 
			
		||||
	Type        RequestType `json:"type"`
 | 
			
		||||
	Description string      `json:"description"`
 | 
			
		||||
	Opts        []Named     `json:"opts"`
 | 
			
		||||
	Inputs      []Named     `json:"inputs"`
 | 
			
		||||
	Metadata    []Named     `json:"metadata"`
 | 
			
		||||
	Refs        []Named     `json:"refs"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Named struct {
 | 
			
		||||
	Name        string `json:"name"`
 | 
			
		||||
	Description string `json:"description"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type RequestType string
 | 
			
		||||
 | 
			
		||||
const TypeRPC RequestType = "rpc"
 | 
			
		||||
		Reference in New Issue
	
	Block a user