controller: remove remaining parts of the controller
Removes all references to the controller and moves the remaining sections of code to other packages. Processes has been moved to monitor where it is used and the data structs have been removed so buildflags is used directly. The controller build function has been moved to the commands package. Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
This commit is contained in:
+26
-87
@@ -7,7 +7,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
controllerapi "github.com/docker/buildx/controller/pb"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tonistiigi/go-csvvalue"
|
||||
)
|
||||
@@ -33,16 +32,32 @@ func (a Attests) Normalize() Attests {
|
||||
return removeAttestDupes(a)
|
||||
}
|
||||
|
||||
func (a Attests) ToPB() []*controllerapi.Attest {
|
||||
if len(a) == 0 {
|
||||
return nil
|
||||
}
|
||||
func (a Attests) ToMap() map[string]*string {
|
||||
result := map[string]*string{}
|
||||
for _, attest := range a {
|
||||
// ignore duplicates
|
||||
if _, ok := result[attest.Type]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
entries := make([]*controllerapi.Attest, len(a))
|
||||
for i, entry := range a {
|
||||
entries[i] = entry.ToPB()
|
||||
if attest.Disabled {
|
||||
result[attest.Type] = nil
|
||||
continue
|
||||
}
|
||||
|
||||
var b csvBuilder
|
||||
if attest.Type != "" {
|
||||
b.Write("type", attest.Type)
|
||||
}
|
||||
if attest.Disabled {
|
||||
b.Write("disabled", "true")
|
||||
}
|
||||
b.WriteAttributes(attest.Attrs)
|
||||
|
||||
s := b.String()
|
||||
result[attest.Type] = &s
|
||||
}
|
||||
return entries
|
||||
return result
|
||||
}
|
||||
|
||||
type Attest struct {
|
||||
@@ -72,23 +87,6 @@ func (a *Attest) String() string {
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (a *Attest) ToPB() *controllerapi.Attest {
|
||||
var b csvBuilder
|
||||
if a.Type != "" {
|
||||
b.Write("type", a.Type)
|
||||
}
|
||||
if a.Disabled {
|
||||
b.Write("disabled", "true")
|
||||
}
|
||||
b.WriteAttributes(a.Attrs)
|
||||
|
||||
return &controllerapi.Attest{
|
||||
Type: a.Type,
|
||||
Disabled: a.Disabled,
|
||||
Attrs: b.String(),
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Attest) MarshalJSON() ([]byte, error) {
|
||||
m := make(map[string]any, len(a.Attrs)+2)
|
||||
for k, v := range a.Attrs {
|
||||
@@ -182,7 +180,7 @@ func CanonicalizeAttest(attestType string, in string) string {
|
||||
return fmt.Sprintf("type=%s,%s", attestType, in)
|
||||
}
|
||||
|
||||
func ParseAttests(in []string) ([]*controllerapi.Attest, error) {
|
||||
func ParseAttests(in []string) (Attests, error) {
|
||||
var outs []*Attest
|
||||
for _, s := range in {
|
||||
var out Attest
|
||||
@@ -191,66 +189,7 @@ func ParseAttests(in []string) ([]*controllerapi.Attest, error) {
|
||||
}
|
||||
outs = append(outs, &out)
|
||||
}
|
||||
return ConvertAttests(outs)
|
||||
}
|
||||
|
||||
// ConvertAttests converts Attestations for the controller API from
|
||||
// the ones in this package.
|
||||
//
|
||||
// Attestations of the same type will cause an error. Some tools,
|
||||
// like bake, remove the duplicates before calling this function.
|
||||
func ConvertAttests(in []*Attest) ([]*controllerapi.Attest, error) {
|
||||
out := make([]*controllerapi.Attest, 0, len(in))
|
||||
|
||||
// Check for duplicate attestations while we convert them
|
||||
// to the controller API.
|
||||
found := map[string]struct{}{}
|
||||
for _, attest := range in {
|
||||
if _, ok := found[attest.Type]; ok {
|
||||
return nil, errors.Errorf("duplicate attestation field %s", attest.Type)
|
||||
}
|
||||
found[attest.Type] = struct{}{}
|
||||
out = append(out, attest.ToPB())
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func ParseAttest(in string) (*controllerapi.Attest, error) {
|
||||
if in == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
fields, err := csvvalue.Fields(in, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
attest := controllerapi.Attest{
|
||||
Attrs: in,
|
||||
}
|
||||
for _, field := range fields {
|
||||
key, value, ok := strings.Cut(field, "=")
|
||||
if !ok {
|
||||
return nil, errors.Errorf("invalid value %s", field)
|
||||
}
|
||||
key = strings.TrimSpace(strings.ToLower(key))
|
||||
|
||||
switch key {
|
||||
case "type":
|
||||
attest.Type = value
|
||||
case "disabled":
|
||||
disabled, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "invalid value %s", field)
|
||||
}
|
||||
attest.Disabled = disabled
|
||||
}
|
||||
}
|
||||
if attest.Type == "" {
|
||||
return nil, errors.Errorf("attestation type not specified")
|
||||
}
|
||||
|
||||
return &attest, nil
|
||||
return outs, nil
|
||||
}
|
||||
|
||||
func removeAttestDupes(s []*Attest) []*Attest {
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
package buildflags
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"maps"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
awsconfig "github.com/aws/aws-sdk-go-v2/config"
|
||||
controllerapi "github.com/docker/buildx/controller/pb"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tonistiigi/go-csvvalue"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
@@ -35,22 +30,6 @@ func (o CacheOptions) Normalize() CacheOptions {
|
||||
return removeDupes(o)
|
||||
}
|
||||
|
||||
func (o CacheOptions) ToPB() []*controllerapi.CacheOptionsEntry {
|
||||
if len(o) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var outs []*controllerapi.CacheOptionsEntry
|
||||
for _, entry := range o {
|
||||
pb := entry.ToPB()
|
||||
if !isActive(pb) {
|
||||
continue
|
||||
}
|
||||
outs = append(outs, pb)
|
||||
}
|
||||
return outs
|
||||
}
|
||||
|
||||
type CacheOptionsEntry struct {
|
||||
Type string `json:"type"`
|
||||
Attrs map[string]string `json:"attrs,omitempty"`
|
||||
@@ -81,16 +60,6 @@ func (e *CacheOptionsEntry) String() string {
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (e *CacheOptionsEntry) ToPB() *controllerapi.CacheOptionsEntry {
|
||||
ci := &controllerapi.CacheOptionsEntry{
|
||||
Type: e.Type,
|
||||
Attrs: maps.Clone(e.Attrs),
|
||||
}
|
||||
addGithubToken(ci)
|
||||
addAwsCredentials(ci)
|
||||
return ci
|
||||
}
|
||||
|
||||
func (e *CacheOptionsEntry) MarshalJSON() ([]byte, error) {
|
||||
m := maps.Clone(e.Attrs)
|
||||
if m == nil {
|
||||
@@ -204,75 +173,3 @@ func ParseCacheEntry(in []string) (CacheOptions, error) {
|
||||
}
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
func addGithubToken(ci *controllerapi.CacheOptionsEntry) {
|
||||
if ci.Type != "gha" {
|
||||
return
|
||||
}
|
||||
version, ok := ci.Attrs["version"]
|
||||
if !ok {
|
||||
// https://github.com/actions/toolkit/blob/2b08dc18f261b9fdd978b70279b85cbef81af8bc/packages/cache/src/internal/config.ts#L19
|
||||
if v, ok := os.LookupEnv("ACTIONS_CACHE_SERVICE_V2"); ok {
|
||||
if b, err := strconv.ParseBool(v); err == nil && b {
|
||||
version = "2"
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, ok := ci.Attrs["token"]; !ok {
|
||||
if v, ok := os.LookupEnv("ACTIONS_RUNTIME_TOKEN"); ok {
|
||||
ci.Attrs["token"] = v
|
||||
}
|
||||
}
|
||||
if _, ok := ci.Attrs["url_v2"]; !ok && version == "2" {
|
||||
// https://github.com/actions/toolkit/blob/2b08dc18f261b9fdd978b70279b85cbef81af8bc/packages/cache/src/internal/config.ts#L34-L35
|
||||
if v, ok := os.LookupEnv("ACTIONS_RESULTS_URL"); ok {
|
||||
ci.Attrs["url_v2"] = v
|
||||
}
|
||||
}
|
||||
if _, ok := ci.Attrs["url"]; !ok {
|
||||
// https://github.com/actions/toolkit/blob/2b08dc18f261b9fdd978b70279b85cbef81af8bc/packages/cache/src/internal/config.ts#L28-L33
|
||||
if v, ok := os.LookupEnv("ACTIONS_CACHE_URL"); ok {
|
||||
ci.Attrs["url"] = v
|
||||
} else if v, ok := os.LookupEnv("ACTIONS_RESULTS_URL"); ok {
|
||||
ci.Attrs["url"] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addAwsCredentials(ci *controllerapi.CacheOptionsEntry) {
|
||||
if ci.Type != "s3" {
|
||||
return
|
||||
}
|
||||
_, okAccessKeyID := ci.Attrs["access_key_id"]
|
||||
_, okSecretAccessKey := ci.Attrs["secret_access_key"]
|
||||
// If the user provides access_key_id, secret_access_key, do not override the session token.
|
||||
if okAccessKeyID && okSecretAccessKey {
|
||||
return
|
||||
}
|
||||
ctx := context.TODO()
|
||||
awsConfig, err := awsconfig.LoadDefaultConfig(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
credentials, err := awsConfig.Credentials.Retrieve(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !okAccessKeyID && credentials.AccessKeyID != "" {
|
||||
ci.Attrs["access_key_id"] = credentials.AccessKeyID
|
||||
}
|
||||
if !okSecretAccessKey && credentials.SecretAccessKey != "" {
|
||||
ci.Attrs["secret_access_key"] = credentials.SecretAccessKey
|
||||
}
|
||||
if _, ok := ci.Attrs["session_token"]; !ok && credentials.SessionToken != "" {
|
||||
ci.Attrs["session_token"] = credentials.SessionToken
|
||||
}
|
||||
}
|
||||
|
||||
func isActive(pb *controllerapi.CacheOptionsEntry) bool {
|
||||
// Always active if not gha.
|
||||
if pb.Type != "gha" {
|
||||
return true
|
||||
}
|
||||
return pb.Attrs["token"] != "" && (pb.Attrs["url"] != "" || pb.Attrs["url_v2"] != "")
|
||||
}
|
||||
|
||||
@@ -4,42 +4,10 @@ import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/buildx/controller/pb"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
func TestCacheOptions_DerivedVars(t *testing.T) {
|
||||
t.Setenv("ACTIONS_RUNTIME_TOKEN", "sensitive_token")
|
||||
t.Setenv("ACTIONS_CACHE_URL", "https://cache.github.com")
|
||||
t.Setenv("AWS_ACCESS_KEY_ID", "definitely_dont_look_here")
|
||||
t.Setenv("AWS_SECRET_ACCESS_KEY", "hackers_please_dont_steal")
|
||||
t.Setenv("AWS_SESSION_TOKEN", "not_a_mitm_attack")
|
||||
|
||||
cacheFrom, err := ParseCacheEntry([]string{"type=gha", "type=s3,region=us-west-2,bucket=my_bucket,name=my_image"})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []*pb.CacheOptionsEntry{
|
||||
{
|
||||
Type: "gha",
|
||||
Attrs: map[string]string{
|
||||
"token": "sensitive_token",
|
||||
"url": "https://cache.github.com",
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: "s3",
|
||||
Attrs: map[string]string{
|
||||
"region": "us-west-2",
|
||||
"bucket": "my_bucket",
|
||||
"name": "my_image",
|
||||
"access_key_id": "definitely_dont_look_here",
|
||||
"secret_access_key": "hackers_please_dont_steal",
|
||||
"session_token": "not_a_mitm_attack",
|
||||
},
|
||||
},
|
||||
}, cacheFrom.ToPB())
|
||||
}
|
||||
|
||||
func TestCacheOptions(t *testing.T) {
|
||||
t.Run("MarshalJSON", func(t *testing.T) {
|
||||
cache := CacheOptions{
|
||||
|
||||
@@ -1,17 +1,37 @@
|
||||
package buildflags
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
controllerapi "github.com/docker/buildx/controller/pb"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tonistiigi/go-csvvalue"
|
||||
)
|
||||
|
||||
const defaultCallFunc = "build"
|
||||
|
||||
func ParseCallFunc(str string) (*controllerapi.CallFunc, error) {
|
||||
type CallFunc struct {
|
||||
Name string
|
||||
Format string
|
||||
IgnoreStatus bool
|
||||
}
|
||||
|
||||
func (x *CallFunc) String() string {
|
||||
var elems []string
|
||||
if x.Name != "" {
|
||||
elems = append(elems, fmt.Sprintf("Name:%q", x.Name))
|
||||
}
|
||||
if x.Format != "" {
|
||||
elems = append(elems, fmt.Sprintf("Format:%q", x.Format))
|
||||
}
|
||||
if x.IgnoreStatus {
|
||||
elems = append(elems, fmt.Sprintf("IgnoreStatus:%v", x.IgnoreStatus))
|
||||
}
|
||||
return strings.Join(elems, " ")
|
||||
}
|
||||
|
||||
func ParseCallFunc(str string) (*CallFunc, error) {
|
||||
if str == "" {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -20,7 +40,7 @@ func ParseCallFunc(str string) (*controllerapi.CallFunc, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f := &controllerapi.CallFunc{}
|
||||
f := &CallFunc{}
|
||||
for _, field := range fields {
|
||||
parts := strings.SplitN(field, "=", 2)
|
||||
if len(parts) == 2 {
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/platforms"
|
||||
controllerapi "github.com/docker/buildx/controller/pb"
|
||||
"github.com/moby/buildkit/client"
|
||||
"github.com/moby/buildkit/exporter/containerimage/exptypes"
|
||||
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
@@ -38,18 +37,6 @@ func (e Exports) Normalize() Exports {
|
||||
return removeDupes(e)
|
||||
}
|
||||
|
||||
func (e Exports) ToPB() []*controllerapi.ExportEntry {
|
||||
if len(e) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
entries := make([]*controllerapi.ExportEntry, len(e))
|
||||
for i, entry := range e {
|
||||
entries[i] = entry.ToPB()
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
type ExportEntry struct {
|
||||
Type string `json:"type"`
|
||||
Attrs map[string]string `json:"attrs,omitempty"`
|
||||
@@ -77,14 +64,6 @@ func (e *ExportEntry) String() string {
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (e *ExportEntry) ToPB() *controllerapi.ExportEntry {
|
||||
return &controllerapi.ExportEntry{
|
||||
Type: e.Type,
|
||||
Attrs: maps.Clone(e.Attrs),
|
||||
Destination: e.Destination,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *ExportEntry) MarshalJSON() ([]byte, error) {
|
||||
m := maps.Clone(e.Attrs)
|
||||
if m == nil {
|
||||
@@ -164,12 +143,12 @@ func (e *ExportEntry) validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ParseExports(inp []string) ([]*controllerapi.ExportEntry, error) {
|
||||
func ParseExports(inp []string) ([]*ExportEntry, error) {
|
||||
if len(inp) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
export := make(Exports, 0, len(inp))
|
||||
exports := make(Exports, 0, len(inp))
|
||||
for _, s := range inp {
|
||||
if s == "" {
|
||||
continue
|
||||
@@ -179,9 +158,9 @@ func ParseExports(inp []string) ([]*controllerapi.ExportEntry, error) {
|
||||
if err := out.UnmarshalText([]byte(s)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
export = append(export, &out)
|
||||
exports = append(exports, &out)
|
||||
}
|
||||
return export.ToPB(), nil
|
||||
return exports, nil
|
||||
}
|
||||
|
||||
func ParseAnnotations(inp []string) (map[exptypes.AnnotationKey]string, error) {
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
controllerapi "github.com/docker/buildx/controller/pb"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tonistiigi/go-csvvalue"
|
||||
)
|
||||
@@ -30,18 +29,6 @@ func (s Secrets) Normalize() Secrets {
|
||||
return removeSecretDupes(s)
|
||||
}
|
||||
|
||||
func (s Secrets) ToPB() []*controllerapi.Secret {
|
||||
if len(s) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
entries := make([]*controllerapi.Secret, len(s))
|
||||
for i, entry := range s {
|
||||
entries[i] = entry.ToPB()
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
type Secret struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
FilePath string `json:"src,omitempty"`
|
||||
@@ -66,14 +53,6 @@ func (s *Secret) String() string {
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (s *Secret) ToPB() *controllerapi.Secret {
|
||||
return &controllerapi.Secret{
|
||||
ID: s.ID,
|
||||
FilePath: s.FilePath,
|
||||
Env: s.Env,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Secret) UnmarshalJSON(data []byte) error {
|
||||
var v struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
@@ -132,8 +111,8 @@ func (s *Secret) UnmarshalText(text []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ParseSecretSpecs(sl []string) ([]*controllerapi.Secret, error) {
|
||||
fs := make([]*controllerapi.Secret, 0, len(sl))
|
||||
func ParseSecretSpecs(sl []string) (Secrets, error) {
|
||||
fs := make([]*Secret, 0, len(sl))
|
||||
for _, v := range sl {
|
||||
if v == "" {
|
||||
continue
|
||||
@@ -148,12 +127,12 @@ func ParseSecretSpecs(sl []string) ([]*controllerapi.Secret, error) {
|
||||
return fs, nil
|
||||
}
|
||||
|
||||
func parseSecret(value string) (*controllerapi.Secret, error) {
|
||||
func parseSecret(value string) (*Secret, error) {
|
||||
var s Secret
|
||||
if err := s.UnmarshalText([]byte(value)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.ToPB(), nil
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
func removeSecretDupes(s []*Secret) []*Secret {
|
||||
|
||||
+3
-23
@@ -6,7 +6,6 @@ import (
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
controllerapi "github.com/docker/buildx/controller/pb"
|
||||
"github.com/moby/buildkit/util/gitutil"
|
||||
)
|
||||
|
||||
@@ -31,18 +30,6 @@ func (s SSHKeys) Normalize() SSHKeys {
|
||||
return removeSSHDupes(s)
|
||||
}
|
||||
|
||||
func (s SSHKeys) ToPB() []*controllerapi.SSH {
|
||||
if len(s) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
entries := make([]*controllerapi.SSH, len(s))
|
||||
for i, entry := range s {
|
||||
entries[i] = entry.ToPB()
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
type SSH struct {
|
||||
ID string `json:"id,omitempty" cty:"id"`
|
||||
Paths []string `json:"paths,omitempty" cty:"paths"`
|
||||
@@ -70,13 +57,6 @@ func (s *SSH) String() string {
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (s *SSH) ToPB() *controllerapi.SSH {
|
||||
return &controllerapi.SSH{
|
||||
ID: s.ID,
|
||||
Paths: s.Paths,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SSH) UnmarshalJSON(data []byte) error {
|
||||
var v struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
@@ -103,8 +83,8 @@ func (s *SSH) UnmarshalText(text []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ParseSSHSpecs(sl []string) ([]*controllerapi.SSH, error) {
|
||||
var outs []*controllerapi.SSH
|
||||
func ParseSSHSpecs(sl []string) ([]*SSH, error) {
|
||||
var outs []*SSH
|
||||
if len(sl) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -118,7 +98,7 @@ func ParseSSHSpecs(sl []string) ([]*controllerapi.SSH, error) {
|
||||
if err := out.UnmarshalText([]byte(s)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outs = append(outs, out.ToPB())
|
||||
outs = append(outs, &out)
|
||||
}
|
||||
return outs, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user