mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 10:03:42 +08:00 
			
		
		
		
	Strongly typing the API allows us to perform all command line parsing fully on the client-side, where we have access to the client local directory and all the client environment variables, which may not be available on the remote server. Additionally, the controller api starts to look a lot like build.Options, so at some point in the future there may be an oppportunity to merge the two, which would allow both build and bake to execute through the controller, instead of needing to maintain multiple code paths. Signed-off-by: Justin Chadwell <me@jedevc.com>
		
			
				
	
	
		
			110 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			110 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package buildflags
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"encoding/csv"
 | 
						|
	"os"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	awsconfig "github.com/aws/aws-sdk-go-v2/config"
 | 
						|
	controllerapi "github.com/docker/buildx/controller/pb"
 | 
						|
	"github.com/pkg/errors"
 | 
						|
)
 | 
						|
 | 
						|
func ParseCacheEntry(in []string) ([]*controllerapi.CacheOptionsEntry, error) {
 | 
						|
	outs := make([]*controllerapi.CacheOptionsEntry, 0, len(in))
 | 
						|
	for _, in := range in {
 | 
						|
		csvReader := csv.NewReader(strings.NewReader(in))
 | 
						|
		fields, err := csvReader.Read()
 | 
						|
		if err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
		if isRefOnlyFormat(fields) {
 | 
						|
			for _, field := range fields {
 | 
						|
				outs = append(outs, &controllerapi.CacheOptionsEntry{
 | 
						|
					Type:  "registry",
 | 
						|
					Attrs: map[string]string{"ref": field},
 | 
						|
				})
 | 
						|
			}
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		out := controllerapi.CacheOptionsEntry{
 | 
						|
			Attrs: map[string]string{},
 | 
						|
		}
 | 
						|
		for _, field := range fields {
 | 
						|
			parts := strings.SplitN(field, "=", 2)
 | 
						|
			if len(parts) != 2 {
 | 
						|
				return nil, errors.Errorf("invalid value %s", field)
 | 
						|
			}
 | 
						|
			key := strings.ToLower(parts[0])
 | 
						|
			value := parts[1]
 | 
						|
			switch key {
 | 
						|
			case "type":
 | 
						|
				out.Type = value
 | 
						|
			default:
 | 
						|
				out.Attrs[key] = value
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if out.Type == "" {
 | 
						|
			return nil, errors.Errorf("type required form> %q", in)
 | 
						|
		}
 | 
						|
		if !addGithubToken(&out) {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		addAwsCredentials(&out)
 | 
						|
		outs = append(outs, &out)
 | 
						|
	}
 | 
						|
	return outs, nil
 | 
						|
}
 | 
						|
 | 
						|
func isRefOnlyFormat(in []string) bool {
 | 
						|
	for _, v := range in {
 | 
						|
		if strings.Contains(v, "=") {
 | 
						|
			return false
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
func addGithubToken(ci *controllerapi.CacheOptionsEntry) bool {
 | 
						|
	if ci.Type != "gha" {
 | 
						|
		return true
 | 
						|
	}
 | 
						|
	if _, ok := ci.Attrs["token"]; !ok {
 | 
						|
		if v, ok := os.LookupEnv("ACTIONS_RUNTIME_TOKEN"); ok {
 | 
						|
			ci.Attrs["token"] = v
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if _, ok := ci.Attrs["url"]; !ok {
 | 
						|
		if v, ok := os.LookupEnv("ACTIONS_CACHE_URL"); ok {
 | 
						|
			ci.Attrs["url"] = v
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return ci.Attrs["token"] != "" && ci.Attrs["url"] != ""
 | 
						|
}
 | 
						|
 | 
						|
func addAwsCredentials(ci *controllerapi.CacheOptionsEntry) {
 | 
						|
	if ci.Type != "s3" {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	ctx := context.TODO()
 | 
						|
	awsConfig, err := awsconfig.LoadDefaultConfig(ctx)
 | 
						|
	if err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	credentials, err := awsConfig.Credentials.Retrieve(ctx)
 | 
						|
	if err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if _, ok := ci.Attrs["access_key_id"]; !ok && credentials.AccessKeyID != "" {
 | 
						|
		ci.Attrs["access_key_id"] = credentials.AccessKeyID
 | 
						|
	}
 | 
						|
	if _, ok := ci.Attrs["secret_access_key"]; !ok && credentials.SecretAccessKey != "" {
 | 
						|
		ci.Attrs["secret_access_key"] = credentials.SecretAccessKey
 | 
						|
	}
 | 
						|
	if _, ok := ci.Attrs["session_token"]; !ok && credentials.SessionToken != "" {
 | 
						|
		ci.Attrs["session_token"] = credentials.SessionToken
 | 
						|
	}
 | 
						|
}
 |