mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-19 18:07:45 +08:00

Removes gogo/protobuf from buildx and updates to a version of moby/buildkit where gogo is removed. This also changes how the proto files are generated. This is because newer versions of protobuf are more strict about name conflicts. If two files have the same name (even if they are relative paths) and are used in different protoc commands, they'll conflict in the registry. Since protobuf file generation doesn't work very well with `paths=source_relative`, this removes the `go:generate` expression and just relies on the dockerfile to perform the generation. Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
169 lines
4.3 KiB
Go
169 lines
4.3 KiB
Go
package apicaps
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
|
|
pb "github.com/moby/buildkit/util/apicaps/pb"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type PBCap = pb.APICap
|
|
|
|
// ExportedProduct is the name of the product using this package.
|
|
// Users vendoring this library may override it to provide better versioning hints
|
|
// for their users (or set it with a flag to buildkitd).
|
|
var ExportedProduct string
|
|
|
|
// CapStatus defines the stability properties of a capability
|
|
type CapStatus int
|
|
|
|
const (
|
|
// CapStatusStable refers to a capability that should never be changed in
|
|
// backwards incompatible manner unless there is a serious security issue.
|
|
CapStatusStable CapStatus = iota
|
|
// CapStatusExperimental refers to a capability that may be removed in the future.
|
|
// If incompatible changes are made the previous ID is disabled and new is added.
|
|
CapStatusExperimental
|
|
// CapStatusPrerelease is same as CapStatusExperimental that can be used for new
|
|
// features before they move to stable.
|
|
CapStatusPrerelease
|
|
)
|
|
|
|
// CapID is type for capability identifier
|
|
type CapID string
|
|
|
|
// Cap describes an API feature
|
|
type Cap struct {
|
|
ID CapID
|
|
Name string // readable name, may contain spaces but keep in one sentence
|
|
Status CapStatus
|
|
Enabled bool
|
|
Deprecated bool
|
|
SupportedHint map[string]string
|
|
DisabledReason string
|
|
DisabledReasonMsg string
|
|
DisabledAlternative string
|
|
}
|
|
|
|
// CapList is a collection of capability definitions
|
|
type CapList struct {
|
|
m map[CapID]Cap
|
|
}
|
|
|
|
// Init initializes definition for a new capability.
|
|
// Not safe to be called concurrently with other methods.
|
|
func (l *CapList) Init(cc ...Cap) {
|
|
if l.m == nil {
|
|
l.m = make(map[CapID]Cap, len(cc))
|
|
}
|
|
for _, c := range cc {
|
|
l.m[c.ID] = c
|
|
}
|
|
}
|
|
|
|
// All reports the configuration of all known capabilities
|
|
func (l *CapList) All() []*pb.APICap {
|
|
out := make([]*pb.APICap, 0, len(l.m))
|
|
for _, c := range l.m {
|
|
out = append(out, &pb.APICap{
|
|
ID: string(c.ID),
|
|
Enabled: c.Enabled,
|
|
Deprecated: c.Deprecated,
|
|
DisabledReason: c.DisabledReason,
|
|
DisabledReasonMsg: c.DisabledReasonMsg,
|
|
DisabledAlternative: c.DisabledAlternative,
|
|
})
|
|
}
|
|
sort.Slice(out, func(i, j int) bool {
|
|
return out[i].ID < out[j].ID
|
|
})
|
|
return out
|
|
}
|
|
|
|
// CapSet returns a CapSet for an capability configuration
|
|
func (l *CapList) CapSet(caps []*pb.APICap) CapSet {
|
|
m := make(map[string]*pb.APICap, len(caps))
|
|
for _, c := range caps {
|
|
if c.ID != "" {
|
|
m[c.ID] = c
|
|
}
|
|
}
|
|
return CapSet{
|
|
list: l,
|
|
set: m,
|
|
}
|
|
}
|
|
|
|
// CapSet is a configuration for detecting supported capabilities
|
|
type CapSet struct {
|
|
list *CapList
|
|
set map[string]*pb.APICap
|
|
}
|
|
|
|
// Supports returns an error if capability is not supported
|
|
func (s *CapSet) Supports(id CapID) error {
|
|
err := &CapError{ID: id}
|
|
c, ok := s.list.m[id]
|
|
if !ok {
|
|
return errors.WithStack(err)
|
|
}
|
|
err.Definition = &c
|
|
state, ok := s.set[string(id)]
|
|
if !ok {
|
|
return errors.WithStack(err)
|
|
}
|
|
err.State = state
|
|
if !state.Enabled {
|
|
return errors.WithStack(err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Contains checks if cap set contains cap. Note that unlike Supports() this
|
|
// function only checks capability existence in remote set, not if cap has been initialized.
|
|
func (s *CapSet) Contains(id CapID) bool {
|
|
_, ok := s.set[string(id)]
|
|
return ok
|
|
}
|
|
|
|
// CapError is an error for unsupported capability
|
|
type CapError struct {
|
|
ID CapID
|
|
Definition *Cap
|
|
State *pb.APICap
|
|
}
|
|
|
|
func (e CapError) Error() string {
|
|
if e.Definition == nil {
|
|
return fmt.Sprintf("unknown API capability %s", e.ID)
|
|
}
|
|
typ := ""
|
|
if e.Definition.Status == CapStatusExperimental {
|
|
typ = "experimental "
|
|
}
|
|
if e.Definition.Status == CapStatusPrerelease {
|
|
typ = "prerelease "
|
|
}
|
|
name := ""
|
|
if e.Definition.Name != "" {
|
|
name = "(" + e.Definition.Name + ")"
|
|
}
|
|
b := &strings.Builder{}
|
|
fmt.Fprintf(b, "requested %sfeature %s %s", typ, e.ID, name)
|
|
if e.State == nil {
|
|
fmt.Fprint(b, " is not supported by build server")
|
|
if hint, ok := e.Definition.SupportedHint[ExportedProduct]; ok {
|
|
fmt.Fprintf(b, " (added in %s)", hint)
|
|
}
|
|
fmt.Fprintf(b, ", please update %s", ExportedProduct)
|
|
} else {
|
|
fmt.Fprint(b, " has been disabled on the build server")
|
|
if e.State.DisabledReasonMsg != "" {
|
|
fmt.Fprintf(b, ": %s", e.State.DisabledReasonMsg)
|
|
}
|
|
}
|
|
return b.String()
|
|
}
|