2018-04-19 03:00:15 +08:00
package parse
// this package should contain functions that parse and validate
// user input and is shared either amongst buildah subcommands or
// would be useful to projects vendoring buildah
import (
2022-07-06 17:14:06 +08:00
"errors"
2018-04-19 03:00:15 +08:00
"fmt"
2024-04-11 16:46:51 +08:00
"io/fs"
2018-04-19 03:00:15 +08:00
"net"
"os"
2018-04-30 06:36:35 +08:00
"path/filepath"
2018-06-07 12:45:17 +08:00
"strconv"
2018-04-19 03:00:15 +08:00
"strings"
2018-06-07 12:45:17 +08:00
"unicode"
2018-04-19 03:00:15 +08:00
2024-08-06 04:51:08 +08:00
"github.com/containerd/platforms"
2021-02-07 06:49:40 +08:00
"github.com/containers/buildah/define"
2023-07-18 04:27:19 +08:00
mkcwtypes "github.com/containers/buildah/internal/mkcw/types"
2021-10-18 13:51:51 +08:00
internalParse "github.com/containers/buildah/internal/parse"
2023-12-05 03:05:38 +08:00
"github.com/containers/buildah/internal/sbom"
2023-09-12 20:35:12 +08:00
"github.com/containers/buildah/internal/tmpdir"
2021-07-26 14:07:23 +08:00
"github.com/containers/buildah/pkg/sshagent"
2023-09-07 21:43:22 +08:00
"github.com/containers/common/pkg/auth"
2022-09-09 22:21:32 +08:00
"github.com/containers/common/pkg/config"
2021-07-12 22:41:28 +08:00
"github.com/containers/common/pkg/parse"
2022-07-18 13:47:55 +08:00
"github.com/containers/image/v5/docker/reference"
2019-10-26 05:19:30 +08:00
"github.com/containers/image/v5/types"
2024-04-11 16:46:51 +08:00
"github.com/containers/storage/pkg/fileutils"
2018-06-07 12:45:17 +08:00
"github.com/containers/storage/pkg/idtools"
2020-07-07 22:15:40 +08:00
"github.com/containers/storage/pkg/unshare"
2022-06-20 15:29:56 +08:00
storageTypes "github.com/containers/storage/types"
2023-02-01 11:34:07 +08:00
securejoin "github.com/cyphar/filepath-securejoin"
2019-10-02 04:03:57 +08:00
units "github.com/docker/go-units"
specs "github.com/opencontainers/runtime-spec/specs-go"
2021-10-07 21:10:22 +08:00
"github.com/openshift/imagebuilder"
2018-06-07 12:45:17 +08:00
"github.com/sirupsen/logrus"
2019-04-07 00:03:58 +08:00
"github.com/spf13/cobra"
2022-01-08 06:09:21 +08:00
"github.com/spf13/pflag"
2021-08-25 03:30:13 +08:00
"golang.org/x/term"
2018-04-19 03:00:15 +08:00
)
const (
// SeccompDefaultPath defines the default seccomp path
2022-09-09 22:21:32 +08:00
SeccompDefaultPath = config . SeccompDefaultPath
2018-04-19 03:00:15 +08:00
// SeccompOverridePath if this exists it overrides the default seccomp path
2022-09-09 22:21:32 +08:00
SeccompOverridePath = config . SeccompOverridePath
2019-06-20 02:17:11 +08:00
// TypeBind is the type for mounting host dir
TypeBind = "bind"
// TypeTmpfs is the type for mounting tmpfs
TypeTmpfs = "tmpfs"
2021-10-07 16:27:17 +08:00
// TypeCache is the type for mounting a common persistent cache from host
TypeCache = "cache"
2023-01-06 02:16:11 +08:00
// mount=type=cache must create a persistent directory on host so it's available for all consecutive builds.
2021-10-07 16:27:17 +08:00
// Lifecycle of following directory will be inherited from how host machine treats temporary directory
BuildahCacheDir = "buildah-cache"
2019-06-20 02:17:11 +08:00
)
2024-10-17 05:09:41 +08:00
var errInvalidSecretSyntax = errors . New ( "incorrect secret flag format: should be --secret id=foo,src=bar[,env=ENV][,type=file|env]" )
2022-12-05 14:29:19 +08:00
// RepoNamesToNamedReferences parse the raw string to Named reference
func RepoNamesToNamedReferences ( destList [ ] string ) ( [ ] reference . Named , error ) {
var result [ ] reference . Named
for _ , dest := range destList {
named , err := reference . ParseNormalizedNamed ( dest )
if err != nil {
return nil , fmt . Errorf ( "invalid repo %q: must contain registry and repository: %w" , dest , err )
}
if ! reference . IsNameOnly ( named ) {
return nil , fmt . Errorf ( "repository must contain neither a tag nor digest: %v" , named )
}
result = append ( result , named )
2022-07-18 13:47:55 +08:00
}
2022-12-05 14:29:19 +08:00
return result , nil
2022-07-18 13:47:55 +08:00
}
2018-06-07 12:45:17 +08:00
// CommonBuildOptions parses the build options from the bud cli
2021-02-07 06:49:40 +08:00
func CommonBuildOptions ( c * cobra . Command ) ( * define . CommonBuildOptions , error ) {
2022-01-08 06:09:21 +08:00
return CommonBuildOptionsFromFlagSet ( c . Flags ( ) , c . Flag )
}
// CommonBuildOptionsFromFlagSet parses the build options from the bud cli
func CommonBuildOptionsFromFlagSet ( flags * pflag . FlagSet , findFlagFunc func ( name string ) * pflag . Flag ) ( * define . CommonBuildOptions , error ) {
2018-04-19 03:00:15 +08:00
var (
memoryLimit int64
memorySwap int64
2019-06-07 03:44:23 +08:00
noDNS bool
2018-04-19 03:00:15 +08:00
err error
)
2019-04-26 03:39:49 +08:00
2022-01-08 06:09:21 +08:00
memVal , _ := flags . GetString ( "memory" )
2019-01-22 23:35:52 +08:00
if memVal != "" {
memoryLimit , err = units . RAMInBytes ( memVal )
2018-04-19 03:00:15 +08:00
if err != nil {
2022-07-06 17:14:06 +08:00
return nil , fmt . Errorf ( "invalid value for memory: %w" , err )
2018-04-19 03:00:15 +08:00
}
}
2019-01-22 23:35:52 +08:00
2022-01-08 06:09:21 +08:00
memSwapValue , _ := flags . GetString ( "memory-swap" )
2019-01-22 23:35:52 +08:00
if memSwapValue != "" {
2021-12-15 18:28:31 +08:00
if memSwapValue == "-1" {
memorySwap = - 1
} else {
memorySwap , err = units . RAMInBytes ( memSwapValue )
if err != nil {
2022-07-06 17:14:06 +08:00
return nil , fmt . Errorf ( "invalid value for memory-swap: %w" , err )
2021-12-15 18:28:31 +08:00
}
2018-04-19 03:00:15 +08:00
}
}
2019-01-22 23:35:52 +08:00
2023-10-25 07:43:56 +08:00
noHostname , _ := flags . GetBool ( "no-hostname" )
2022-03-08 04:44:14 +08:00
noHosts , _ := flags . GetBool ( "no-hosts" )
2022-01-08 06:09:21 +08:00
addHost , _ := flags . GetStringSlice ( "add-host" )
2019-01-22 23:35:52 +08:00
if len ( addHost ) > 0 {
2022-03-08 04:44:14 +08:00
if noHosts {
2022-07-06 17:14:06 +08:00
return nil , errors . New ( "--no-hosts and --add-host conflict, can not be used together" )
2022-03-08 04:44:14 +08:00
}
2019-01-22 23:35:52 +08:00
for _ , host := range addHost {
2018-04-19 03:00:15 +08:00
if err := validateExtraHost ( host ) ; err != nil {
2022-07-06 17:14:06 +08:00
return nil , fmt . Errorf ( "invalid value for add-host: %w" , err )
2018-04-19 03:00:15 +08:00
}
}
}
2019-04-07 00:03:58 +08:00
2019-06-07 03:44:23 +08:00
noDNS = false
2020-02-08 01:54:18 +08:00
dnsServers := [ ] string { }
2022-01-08 06:09:21 +08:00
if flags . Changed ( "dns" ) {
dnsServers , _ = flags . GetStringSlice ( "dns" )
2020-02-08 01:54:18 +08:00
for _ , server := range dnsServers {
if strings . ToLower ( server ) == "none" {
noDNS = true
}
}
if noDNS && len ( dnsServers ) > 1 {
2022-07-06 17:14:06 +08:00
return nil , errors . New ( "invalid --dns, --dns=none may not be used with any other --dns options" )
2019-06-07 03:44:23 +08:00
}
}
2020-02-08 01:54:18 +08:00
dnsSearch := [ ] string { }
2022-01-08 06:09:21 +08:00
if flags . Changed ( "dns-search" ) {
dnsSearch , _ = flags . GetStringSlice ( "dns-search" )
2020-02-08 01:54:18 +08:00
if noDNS && len ( dnsSearch ) > 0 {
2022-07-06 17:14:06 +08:00
return nil , errors . New ( "invalid --dns-search, --dns-search may not be used with --dns=none" )
2020-02-08 01:54:18 +08:00
}
2019-06-07 03:44:23 +08:00
}
2020-02-08 01:54:18 +08:00
dnsOptions := [ ] string { }
2022-01-08 06:09:21 +08:00
if flags . Changed ( "dns-option" ) {
dnsOptions , _ = flags . GetStringSlice ( "dns-option" )
2020-02-08 01:54:18 +08:00
if noDNS && len ( dnsOptions ) > 0 {
2022-07-06 17:14:06 +08:00
return nil , errors . New ( "invalid --dns-option, --dns-option may not be used with --dns=none" )
2020-02-08 01:54:18 +08:00
}
2019-06-07 03:44:23 +08:00
}
2019-04-07 00:03:58 +08:00
2022-01-08 06:09:21 +08:00
if _ , err := units . FromHumanSize ( findFlagFunc ( "shm-size" ) . Value . String ( ) ) ; err != nil {
2022-07-06 17:14:06 +08:00
return nil , fmt . Errorf ( "invalid --shm-size: %w" , err )
2018-04-19 03:00:15 +08:00
}
2022-01-08 06:09:21 +08:00
volumes , _ := flags . GetStringArray ( "volume" )
cpuPeriod , _ := flags . GetUint64 ( "cpu-period" )
cpuQuota , _ := flags . GetInt64 ( "cpu-quota" )
cpuShares , _ := flags . GetUint64 ( "cpu-shares" )
httpProxy , _ := flags . GetBool ( "http-proxy" )
2022-04-04 13:37:01 +08:00
identityLabel , _ := flags . GetBool ( "identity-label" )
2022-06-01 15:59:52 +08:00
omitHistory , _ := flags . GetBool ( "omit-history" )
2020-02-08 01:54:18 +08:00
ulimit := [ ] string { }
2022-01-08 06:09:21 +08:00
if flags . Changed ( "ulimit" ) {
ulimit , _ = flags . GetStringSlice ( "ulimit" )
2020-02-08 01:54:18 +08:00
}
2020-01-14 20:12:56 +08:00
2022-01-08 06:09:21 +08:00
secrets , _ := flags . GetStringArray ( "secret" )
sshsources , _ := flags . GetStringArray ( "ssh" )
2022-06-22 18:48:00 +08:00
ociHooks , _ := flags . GetStringArray ( "hooks-dir" )
2021-04-17 06:21:31 +08:00
2021-02-07 06:49:40 +08:00
commonOpts := & define . CommonBuildOptions {
2022-04-04 13:37:01 +08:00
AddHost : addHost ,
CPUPeriod : cpuPeriod ,
CPUQuota : cpuQuota ,
CPUSetCPUs : findFlagFunc ( "cpuset-cpus" ) . Value . String ( ) ,
CPUSetMems : findFlagFunc ( "cpuset-mems" ) . Value . String ( ) ,
CPUShares : cpuShares ,
CgroupParent : findFlagFunc ( "cgroup-parent" ) . Value . String ( ) ,
DNSOptions : dnsOptions ,
DNSSearch : dnsSearch ,
DNSServers : dnsServers ,
HTTPProxy : httpProxy ,
IdentityLabel : types . NewOptionalBool ( identityLabel ) ,
Memory : memoryLimit ,
MemorySwap : memorySwap ,
2023-10-25 07:43:56 +08:00
NoHostname : noHostname ,
2022-04-04 13:37:01 +08:00
NoHosts : noHosts ,
2022-06-01 15:59:52 +08:00
OmitHistory : omitHistory ,
2022-04-04 13:37:01 +08:00
ShmSize : findFlagFunc ( "shm-size" ) . Value . String ( ) ,
Ulimit : ulimit ,
Volumes : volumes ,
Secrets : secrets ,
SSHSources : sshsources ,
2022-06-22 18:48:00 +08:00
OCIHooksDir : ociHooks ,
2018-04-19 03:00:15 +08:00
}
2022-01-08 06:09:21 +08:00
securityOpts , _ := flags . GetStringArray ( "security-opt" )
2019-01-22 23:35:52 +08:00
if err := parseSecurityOpts ( securityOpts , commonOpts ) ; err != nil {
2018-04-19 03:00:15 +08:00
return nil , err
}
return commonOpts , nil
}
2022-05-10 18:11:37 +08:00
// GetAdditionalBuildContext consumes raw string and returns parsed AdditionalBuildContext
func GetAdditionalBuildContext ( value string ) ( define . AdditionalBuildContext , error ) {
ret := define . AdditionalBuildContext { IsURL : false , IsImage : false , Value : value }
if strings . HasPrefix ( value , "docker-image://" ) {
ret . IsImage = true
ret . Value = strings . TrimPrefix ( value , "docker-image://" )
} else if strings . HasPrefix ( value , "container-image://" ) {
ret . IsImage = true
ret . Value = strings . TrimPrefix ( value , "container-image://" )
} else if strings . HasPrefix ( value , "docker://" ) {
ret . IsImage = true
ret . Value = strings . TrimPrefix ( value , "docker://" )
} else if strings . HasPrefix ( value , "http://" ) || strings . HasPrefix ( value , "https://" ) {
ret . IsImage = false
ret . IsURL = true
} else {
path , err := filepath . Abs ( value )
if err != nil {
2022-07-06 17:14:06 +08:00
return define . AdditionalBuildContext { } , fmt . Errorf ( "unable to convert additional build-context %q path to absolute: %w" , value , err )
2022-05-10 18:11:37 +08:00
}
ret . Value = path
}
return ret , nil
}
2021-02-07 06:49:40 +08:00
func parseSecurityOpts ( securityOpts [ ] string , commonOpts * define . CommonBuildOptions ) error {
2018-04-19 03:00:15 +08:00
for _ , opt := range securityOpts {
if opt == "no-new-privileges" {
2022-11-04 19:04:16 +08:00
commonOpts . NoNewPrivileges = true
continue
2018-04-19 03:00:15 +08:00
}
2022-11-04 19:04:16 +08:00
2018-04-19 03:00:15 +08:00
con := strings . SplitN ( opt , "=" , 2 )
if len ( con ) != 2 {
2022-07-06 17:14:06 +08:00
return fmt . Errorf ( "invalid --security-opt name=value pair: %q" , opt )
2018-04-19 03:00:15 +08:00
}
switch con [ 0 ] {
case "label" :
commonOpts . LabelOpts = append ( commonOpts . LabelOpts , con [ 1 ] )
case "apparmor" :
commonOpts . ApparmorProfile = con [ 1 ]
case "seccomp" :
commonOpts . SeccompProfilePath = con [ 1 ]
2024-12-18 23:47:40 +08:00
case "mask" :
commonOpts . Masks = append ( commonOpts . Masks , strings . Split ( con [ 1 ] , ":" ) ... )
case "unmask" :
unmasks := strings . Split ( con [ 1 ] , ":" )
for _ , unmask := range unmasks {
matches , _ := filepath . Glob ( unmask )
if len ( matches ) > 0 {
commonOpts . Unmasks = append ( commonOpts . Unmasks , matches ... )
continue
}
commonOpts . Unmasks = append ( commonOpts . Unmasks , unmask )
}
2018-04-19 03:00:15 +08:00
default :
2022-07-06 17:14:06 +08:00
return fmt . Errorf ( "invalid --security-opt 2: %q" , opt )
2018-04-19 03:00:15 +08:00
}
}
if commonOpts . SeccompProfilePath == "" {
2024-04-11 16:46:51 +08:00
if err := fileutils . Exists ( SeccompOverridePath ) ; err == nil {
2018-04-19 03:00:15 +08:00
commonOpts . SeccompProfilePath = SeccompOverridePath
} else {
2024-04-11 16:46:51 +08:00
if ! errors . Is ( err , fs . ErrNotExist ) {
2022-07-06 17:14:06 +08:00
return err
2018-04-19 03:00:15 +08:00
}
2024-04-11 16:46:51 +08:00
if err := fileutils . Exists ( SeccompDefaultPath ) ; err != nil {
if ! errors . Is ( err , fs . ErrNotExist ) {
2022-07-06 17:14:06 +08:00
return err
2018-04-19 03:00:15 +08:00
}
} else {
commonOpts . SeccompProfilePath = SeccompDefaultPath
}
}
}
return nil
}
2021-10-11 11:26:35 +08:00
// Split string into slice by colon. Backslash-escaped colon (i.e. "\:") will not be regarded as separator
func SplitStringWithColonEscape ( str string ) [ ] string {
2022-03-16 10:59:59 +08:00
return internalParse . SplitStringWithColonEscape ( str )
2021-10-11 11:26:35 +08:00
}
2019-07-24 19:55:25 +08:00
// Volume parses the input of --volume
func Volume ( volume string ) ( specs . Mount , error ) {
2022-03-16 10:59:59 +08:00
return internalParse . Volume ( volume )
2019-04-28 18:33:09 +08:00
}
2019-07-24 19:55:25 +08:00
// Volumes validates the host and container paths passed in to the --volume flag
func Volumes ( volumes [ ] string ) error {
2018-04-19 03:00:15 +08:00
if len ( volumes ) == 0 {
return nil
}
for _ , volume := range volumes {
2019-07-24 19:55:25 +08:00
if _ , err := Volume ( volume ) ; err != nil {
2018-04-19 03:00:15 +08:00
return err
}
}
return nil
}
2019-06-20 02:17:11 +08:00
// ValidateVolumeHostDir validates a volume mount's source directory
2019-05-04 04:45:01 +08:00
func ValidateVolumeHostDir ( hostDir string ) error {
2021-07-12 22:41:28 +08:00
return parse . ValidateVolumeHostDir ( hostDir )
2019-06-20 02:17:11 +08:00
}
// ValidateVolumeCtrDir validates a volume mount's destination directory.
2019-05-04 04:45:01 +08:00
func ValidateVolumeCtrDir ( ctrDir string ) error {
2021-07-12 22:41:28 +08:00
return parse . ValidateVolumeCtrDir ( ctrDir )
2018-04-19 03:00:15 +08:00
}
2019-06-29 04:07:38 +08:00
// ValidateVolumeOpts validates a volume's options
func ValidateVolumeOpts ( options [ ] string ) ( [ ] string , error ) {
2021-07-12 22:41:28 +08:00
return parse . ValidateVolumeOpts ( options )
2018-04-19 03:00:15 +08:00
}
// validateExtraHost validates that the specified string is a valid extrahost and returns it.
// ExtraHost is in the form of name:ip where the ip has to be a valid ip (ipv4 or ipv6).
// for add-host flag
func validateExtraHost ( val string ) error {
// allow for IPv6 addresses in extra hosts by only splitting on first ":"
arr := strings . SplitN ( val , ":" , 2 )
if len ( arr ) != 2 || len ( arr [ 0 ] ) == 0 {
2022-07-06 17:14:06 +08:00
return fmt . Errorf ( "bad format for add-host: %q" , val )
2018-04-19 03:00:15 +08:00
}
if _ , err := validateIPAddress ( arr [ 1 ] ) ; err != nil {
2022-07-06 17:14:06 +08:00
return fmt . Errorf ( "invalid IP address in add-host: %q" , arr [ 1 ] )
2018-04-19 03:00:15 +08:00
}
return nil
}
// validateIPAddress validates an Ip address.
// for dns, ip, and ip6 flags also
func validateIPAddress ( val string ) ( string , error ) {
2024-08-16 00:50:07 +08:00
ip := net . ParseIP ( strings . TrimSpace ( val ) )
2018-04-19 03:00:15 +08:00
if ip != nil {
return ip . String ( ) , nil
}
2022-07-06 17:14:06 +08:00
return "" , fmt . Errorf ( "%s is not an ip address" , val )
2018-04-19 03:00:15 +08:00
}
// SystemContextFromOptions returns a SystemContext populated with values
// per the input parameters provided by the caller for the use in authentication.
2019-01-22 23:35:52 +08:00
func SystemContextFromOptions ( c * cobra . Command ) ( * types . SystemContext , error ) {
2022-01-15 04:39:29 +08:00
return SystemContextFromFlagSet ( c . Flags ( ) , c . Flag )
}
// SystemContextFromFlagSet returns a SystemContext populated with values
// per the input parameters provided by the caller for the use in authentication.
func SystemContextFromFlagSet ( flags * pflag . FlagSet , findFlagFunc func ( name string ) * pflag . Flag ) ( * types . SystemContext , error ) {
certDir , err := flags . GetString ( "cert-dir" )
2019-01-22 23:35:52 +08:00
if err != nil {
certDir = ""
}
2018-04-19 03:00:15 +08:00
ctx := & types . SystemContext {
2019-01-22 23:35:52 +08:00
DockerCertPath : certDir ,
2018-04-19 03:00:15 +08:00
}
2022-01-15 04:39:29 +08:00
tlsVerify , err := flags . GetBool ( "tls-verify" )
if err == nil && findFlagFunc ( "tls-verify" ) . Changed {
2019-02-20 23:25:24 +08:00
ctx . DockerInsecureSkipTLSVerify = types . NewOptionalBool ( ! tlsVerify )
ctx . OCIInsecureSkipTLSVerify = ! tlsVerify
ctx . DockerDaemonInsecureSkipTLSVerify = ! tlsVerify
2018-04-19 03:00:15 +08:00
}
2022-08-17 05:07:22 +08:00
insecure , err := flags . GetBool ( "insecure" )
if err == nil && findFlagFunc ( "insecure" ) . Changed {
if ctx . DockerInsecureSkipTLSVerify != types . OptionalBoolUndefined {
return nil , errors . New ( "--insecure may not be used with --tls-verify" )
}
ctx . DockerInsecureSkipTLSVerify = types . NewOptionalBool ( insecure )
ctx . OCIInsecureSkipTLSVerify = insecure
ctx . DockerDaemonInsecureSkipTLSVerify = insecure
}
2022-01-15 04:39:29 +08:00
disableCompression , err := flags . GetBool ( "disable-compression" )
2021-04-11 01:44:51 +08:00
if err == nil {
if disableCompression {
ctx . OCIAcceptUncompressedLayers = true
} else {
ctx . DirForceCompress = true
}
}
2022-01-15 04:39:29 +08:00
creds , err := flags . GetString ( "creds" )
if err == nil && findFlagFunc ( "creds" ) . Changed {
2018-04-19 03:00:15 +08:00
var err error
2021-03-22 20:02:39 +08:00
ctx . DockerAuthConfig , err = AuthConfig ( creds )
2018-04-19 03:00:15 +08:00
if err != nil {
return nil , err
}
}
2022-01-15 04:39:29 +08:00
sigPolicy , err := flags . GetString ( "signature-policy" )
if err == nil && findFlagFunc ( "signature-policy" ) . Changed {
2019-01-22 23:35:52 +08:00
ctx . SignaturePolicyPath = sigPolicy
2018-04-19 03:00:15 +08:00
}
2022-01-15 04:39:29 +08:00
authfile , err := flags . GetString ( "authfile" )
2019-04-10 03:57:12 +08:00
if err == nil {
ctx . AuthFilePath = getAuthFile ( authfile )
2018-04-19 03:00:15 +08:00
}
2022-01-15 04:39:29 +08:00
regConf , err := flags . GetString ( "registries-conf" )
if err == nil && findFlagFunc ( "registries-conf" ) . Changed {
2019-01-22 23:35:52 +08:00
ctx . SystemRegistriesConfPath = regConf
2018-04-19 03:00:15 +08:00
}
2022-01-15 04:39:29 +08:00
regConfDir , err := flags . GetString ( "registries-conf-dir" )
if err == nil && findFlagFunc ( "registries-conf-dir" ) . Changed {
2019-01-22 23:35:52 +08:00
ctx . RegistriesDirPath = regConfDir
2018-04-19 03:00:15 +08:00
}
2022-01-15 04:39:29 +08:00
shortNameAliasConf , err := flags . GetString ( "short-name-alias-conf" )
if err == nil && findFlagFunc ( "short-name-alias-conf" ) . Changed {
2021-05-12 00:21:09 +08:00
ctx . UserShortNameAliasConfPath = shortNameAliasConf
}
2021-02-07 06:49:40 +08:00
ctx . DockerRegistryUserAgent = fmt . Sprintf ( "Buildah/%s" , define . Version )
2022-01-15 04:39:29 +08:00
if findFlagFunc ( "os" ) != nil && findFlagFunc ( "os" ) . Changed {
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
var os string
2022-01-15 04:39:29 +08:00
if os , err = flags . GetString ( "os" ) ; err != nil {
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
return nil , err
2021-01-05 01:01:23 +08:00
}
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
ctx . OSChoice = os
2019-09-11 06:21:07 +08:00
}
2022-01-15 04:39:29 +08:00
if findFlagFunc ( "arch" ) != nil && findFlagFunc ( "arch" ) . Changed {
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
var arch string
2022-01-15 04:39:29 +08:00
if arch , err = flags . GetString ( "arch" ) ; err != nil {
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
return nil , err
2021-01-05 01:01:23 +08:00
}
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
ctx . ArchitectureChoice = arch
2020-12-23 05:12:38 +08:00
}
2022-01-15 04:39:29 +08:00
if findFlagFunc ( "variant" ) != nil && findFlagFunc ( "variant" ) . Changed {
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
var variant string
2022-01-15 04:39:29 +08:00
if variant , err = flags . GetString ( "variant" ) ; err != nil {
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
return nil , err
2020-12-23 05:12:38 +08:00
}
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
ctx . VariantChoice = variant
2021-01-05 01:01:23 +08:00
}
2022-01-15 04:39:29 +08:00
if findFlagFunc ( "platform" ) != nil && findFlagFunc ( "platform" ) . Changed {
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
var specs [ ] string
2022-01-15 04:39:29 +08:00
if specs , err = flags . GetStringSlice ( "platform" ) ; err != nil {
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
return nil , err
2020-12-23 05:12:38 +08:00
}
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
if len ( specs ) == 0 || specs [ 0 ] == "" {
2022-07-06 17:14:06 +08:00
return nil , fmt . Errorf ( "unable to parse --platform value %v" , specs )
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
}
platform := specs [ 0 ]
os , arch , variant , err := Platform ( platform )
if err != nil {
return nil , err
}
if ctx . OSChoice != "" || ctx . ArchitectureChoice != "" || ctx . VariantChoice != "" {
2022-07-06 17:14:06 +08:00
return nil , errors . New ( "invalid --platform may not be used with --os, --arch, or --variant" )
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
}
ctx . OSChoice = os
ctx . ArchitectureChoice = arch
ctx . VariantChoice = variant
2020-12-23 05:12:38 +08:00
}
2021-01-07 03:47:09 +08:00
ctx . BigFilesTemporaryDir = GetTempDir ( )
2018-04-19 03:00:15 +08:00
return ctx , nil
}
2024-06-22 03:31:59 +08:00
// pullPolicyWithFlags parses a string value of a pull policy, evaluating it in
// combination with "always" and "never" boolean flags.
// Allow for:
// * --pull
// * --pull=""
// * --pull=true
// * --pull=false
// * --pull=never
// * --pull=always
// * --pull=ifmissing
// * --pull=missing
// * --pull=notpresent
// * --pull=newer
// * --pull=ifnewer
// and --pull-always and --pull-never as boolean flags.
func pullPolicyWithFlags ( policySpec string , always , never bool ) ( define . PullPolicy , error ) {
if always {
return define . PullAlways , nil
}
if never {
return define . PullNever , nil
}
policy := strings . ToLower ( policySpec )
switch policy {
case "true" , "missing" , "ifmissing" , "notpresent" :
return define . PullIfMissing , nil
case "always" :
return define . PullAlways , nil
case "false" , "never" :
return define . PullNever , nil
case "ifnewer" , "newer" :
return define . PullIfNewer , nil
}
return 0 , fmt . Errorf ( "unrecognized pull policy %q" , policySpec )
}
2023-12-05 03:05:38 +08:00
// PullPolicyFromOptions returns a PullPolicy that reflects the combination of
// the specified "pull" and undocumented "pull-always" and "pull-never" flags.
func PullPolicyFromOptions ( c * cobra . Command ) ( define . PullPolicy , error ) {
return PullPolicyFromFlagSet ( c . Flags ( ) , c . Flag )
}
// PullPolicyFromFlagSet returns a PullPolicy that reflects the combination of
// the specified "pull" and undocumented "pull-always" and "pull-never" flags.
func PullPolicyFromFlagSet ( flags * pflag . FlagSet , findFlagFunc func ( name string ) * pflag . Flag ) ( define . PullPolicy , error ) {
pullFlagsCount := 0
if findFlagFunc ( "pull" ) . Changed {
pullFlagsCount ++
}
if findFlagFunc ( "pull-always" ) . Changed {
pullFlagsCount ++
}
if findFlagFunc ( "pull-never" ) . Changed {
pullFlagsCount ++
}
if pullFlagsCount > 1 {
return 0 , errors . New ( "can only set one of 'pull' or 'pull-always' or 'pull-never'" )
}
2024-06-22 03:31:59 +08:00
// The --pull-never and --pull-always options will not be documented.
2023-12-05 03:05:38 +08:00
pullAlwaysFlagValue , err := flags . GetBool ( "pull-always" )
if err != nil {
2024-06-22 03:31:59 +08:00
return 0 , fmt . Errorf ( "checking the --pull-always flag value: %w" , err )
2023-12-05 03:05:38 +08:00
}
pullNeverFlagValue , err := flags . GetBool ( "pull-never" )
if err != nil {
2024-06-22 03:31:59 +08:00
return 0 , fmt . Errorf ( "checking the --pull-never flag value: %w" , err )
2023-12-05 03:05:38 +08:00
}
2024-06-22 03:31:59 +08:00
// The --pull[=...] flag is the one we really care about.
pullFlagValue := findFlagFunc ( "pull" ) . Value . String ( )
pullPolicy , err := pullPolicyWithFlags ( pullFlagValue , pullAlwaysFlagValue , pullNeverFlagValue )
if err != nil {
return 0 , err
2023-12-05 03:05:38 +08:00
}
2024-06-22 03:31:59 +08:00
2023-12-05 03:05:38 +08:00
logrus . Debugf ( "Pull Policy for pull [%v]" , pullPolicy )
return pullPolicy , nil
}
2019-04-10 03:57:12 +08:00
func getAuthFile ( authfile string ) string {
if authfile != "" {
2023-09-07 21:43:22 +08:00
absAuthfile , err := filepath . Abs ( authfile )
if err == nil {
return absAuthfile
}
logrus . Warnf ( "ignoring passed-in auth file path, evaluating it: %v" , err )
2019-04-10 03:57:12 +08:00
}
2023-09-07 21:43:22 +08:00
return auth . GetDefaultAuthFile ( )
2019-04-10 03:57:12 +08:00
}
2020-01-20 19:31:09 +08:00
// PlatformFromOptions parses the operating system (os) and architecture (arch)
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
// from the provided command line options. Deprecated in favor of
// PlatformsFromOptions(), but kept here because it's part of our API.
2020-01-20 19:31:09 +08:00
func PlatformFromOptions ( c * cobra . Command ) ( os , arch string , err error ) {
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
platforms , err := PlatformsFromOptions ( c )
if err != nil {
return "" , "" , err
}
if len ( platforms ) < 1 {
2022-07-06 17:14:06 +08:00
return "" , "" , errors . New ( "invalid platform syntax for --platform (use OS/ARCH[/VARIANT])" )
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
}
return platforms [ 0 ] . OS , platforms [ 0 ] . Arch , nil
}
2020-01-20 19:31:09 +08:00
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
// PlatformsFromOptions parses the operating system (os) and architecture
// (arch) from the provided command line options. If --platform used, it
// also returns the list of platforms that were passed in as its argument.
func PlatformsFromOptions ( c * cobra . Command ) ( platforms [ ] struct { OS , Arch , Variant string } , err error ) {
var os , arch , variant string
2021-01-05 01:01:23 +08:00
if c . Flag ( "os" ) . Changed {
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
if os , err = c . Flags ( ) . GetString ( "os" ) ; err != nil {
return nil , err
2021-01-05 01:01:23 +08:00
}
2020-01-20 19:31:09 +08:00
}
2021-01-05 01:01:23 +08:00
if c . Flag ( "arch" ) . Changed {
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
if arch , err = c . Flags ( ) . GetString ( "arch" ) ; err != nil {
return nil , err
2021-01-05 01:01:23 +08:00
}
2020-01-20 19:31:09 +08:00
}
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
if c . Flag ( "variant" ) . Changed {
if variant , err = c . Flags ( ) . GetString ( "variant" ) ; err != nil {
return nil , err
}
}
platforms = [ ] struct { OS , Arch , Variant string } { { os , arch , variant } }
2021-01-05 01:01:23 +08:00
if c . Flag ( "platform" ) . Changed {
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
platforms = nil
platformSpecs , err := c . Flags ( ) . GetStringSlice ( "platform" )
if err != nil {
2022-07-06 17:14:06 +08:00
return nil , fmt . Errorf ( "unable to parse platform: %w" , err )
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
}
if os != "" || arch != "" || variant != "" {
2022-07-06 17:14:06 +08:00
return nil , fmt . Errorf ( "invalid --platform may not be used with --os, --arch, or --variant" )
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
}
for _ , pf := range platformSpecs {
if os , arch , variant , err = Platform ( pf ) ; err != nil {
2022-07-06 17:14:06 +08:00
return nil , fmt . Errorf ( "unable to parse platform %q: %w" , pf , err )
2021-01-05 01:01:23 +08:00
}
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
platforms = append ( platforms , struct { OS , Arch , Variant string } { os , arch , variant } )
2020-01-20 19:31:09 +08:00
}
}
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
return platforms , nil
2020-01-20 19:31:09 +08:00
}
// DefaultPlatform returns the standard platform for the current system
func DefaultPlatform ( ) string {
2021-09-28 05:26:01 +08:00
return platforms . DefaultString ( )
2020-01-20 19:31:09 +08:00
}
bud: teach --platform to take a list
Add a pkg/parse.PlatformsFromOptions() which understands a "variant"
value as an optional third value in an OS/ARCH[/VARIANT] argument value,
which accepts a comma-separated list of them, and which returns a list
of platforms.
Teach "from" and "pull" about the --platform option and add integration
tests for them, warning if --platform was given multiple values.
Add a define.BuildOptions.JobSemaphore which an imagebuildah executor
will use in preference to one that it might allocate for itself.
In main(), allocate a JobSemaphore if the number of jobs is not 0 (which
we treat as "unlimited", and continue to allow executors to do).
In addManifest(), take a lock on the manifest list's image ID so that we
don't overwrite changes that another thread might be making while we're
attempting to make changes to it. In main(), create an empty list if
the list doesn't already exist before we start down this path, so that
we don't get two threads trying to create that manifest list at the same
time later on. Two processes could still try to create the same list
twice, but it's an incremental improvement.
Finally, if we've been given multiple platforms to build for, run their
builds concurrently and gather up their results.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-06-22 22:52:49 +08:00
// Platform separates the platform string into os, arch and variant,
// accepting any of $arch, $os/$arch, or $os/$arch/$variant.
2021-03-31 03:26:24 +08:00
func Platform ( platform string ) ( os , arch , variant string , err error ) {
2023-11-08 06:39:52 +08:00
platform = strings . Trim ( platform , "/" )
if platform == "local" || platform == "" {
2023-04-25 17:46:47 +08:00
return Platform ( DefaultPlatform ( ) )
}
platformSpec , err := platforms . Parse ( platform )
if err != nil {
return "" , "" , "" , fmt . Errorf ( "invalid platform syntax for --platform=%q: %w" , platform , err )
}
return platformSpec . OS , platformSpec . Architecture , platformSpec . Variant , nil
2020-01-20 19:31:09 +08:00
}
2018-04-19 03:00:15 +08:00
func parseCreds ( creds string ) ( string , string ) {
if creds == "" {
return "" , ""
}
up := strings . SplitN ( creds , ":" , 2 )
if len ( up ) == 1 {
return up [ 0 ] , ""
}
if up [ 0 ] == "" {
return "" , up [ 1 ]
}
return up [ 0 ] , up [ 1 ]
}
2021-03-22 20:02:39 +08:00
// AuthConfig parses the creds in format [username[:password] into an auth
// config.
func AuthConfig ( creds string ) ( * types . DockerAuthConfig , error ) {
2018-04-19 03:00:15 +08:00
username , password := parseCreds ( creds )
if username == "" {
fmt . Print ( "Username: " )
2024-08-07 03:10:12 +08:00
if _ , err := fmt . Scanln ( & username ) ; err != nil {
return nil , fmt . Errorf ( "reading user name: %w" , err )
}
2018-04-19 03:00:15 +08:00
}
if password == "" {
fmt . Print ( "Password: " )
2021-08-25 03:30:13 +08:00
termPassword , err := term . ReadPassword ( 0 )
2018-04-19 03:00:15 +08:00
if err != nil {
2022-07-06 17:14:06 +08:00
return nil , fmt . Errorf ( "could not read password from terminal: %w" , err )
2018-04-19 03:00:15 +08:00
}
password = string ( termPassword )
}
return & types . DockerAuthConfig {
Username : username ,
Password : password ,
} , nil
}
2018-06-07 12:45:17 +08:00
2022-04-29 21:39:42 +08:00
// GetBuildOutput is responsible for parsing custom build output argument i.e `build --output` flag.
// Takes `buildOutput` as string and returns BuildOutputOption
func GetBuildOutput ( buildOutput string ) ( define . BuildOutputOption , error ) {
if len ( buildOutput ) == 1 && buildOutput == "-" {
// Feature parity with buildkit, output tar to stdout
// Read more here: https://docs.docker.com/engine/reference/commandline/build/#custom-build-outputs
2024-08-16 00:50:07 +08:00
return define . BuildOutputOption {
Path : "" ,
2022-04-29 21:39:42 +08:00
IsDir : false ,
2024-08-16 00:50:07 +08:00
IsStdout : true ,
} , nil
2022-04-29 21:39:42 +08:00
}
if ! strings . Contains ( buildOutput , "," ) {
// expect default --output <dirname>
2024-08-16 00:50:07 +08:00
return define . BuildOutputOption {
Path : buildOutput ,
2022-04-29 21:39:42 +08:00
IsDir : true ,
2024-08-16 00:50:07 +08:00
IsStdout : false ,
} , nil
2022-04-29 21:39:42 +08:00
}
isDir := true
isStdout := false
typeSelected := false
pathSelected := false
path := ""
tokens := strings . Split ( buildOutput , "," )
for _ , option := range tokens {
arr := strings . SplitN ( option , "=" , 2 )
if len ( arr ) != 2 {
return define . BuildOutputOption { } , fmt . Errorf ( "invalid build output options %q, expected format key=value" , buildOutput )
}
switch arr [ 0 ] {
case "type" :
if typeSelected {
2022-07-06 17:14:06 +08:00
return define . BuildOutputOption { } , fmt . Errorf ( "duplicate %q not supported" , arr [ 0 ] )
2022-04-29 21:39:42 +08:00
}
typeSelected = true
if arr [ 1 ] == "local" {
isDir = true
} else if arr [ 1 ] == "tar" {
isDir = false
} else {
return define . BuildOutputOption { } , fmt . Errorf ( "invalid type %q selected for build output options %q" , arr [ 1 ] , buildOutput )
}
case "dest" :
if pathSelected {
2022-07-06 17:14:06 +08:00
return define . BuildOutputOption { } , fmt . Errorf ( "duplicate %q not supported" , arr [ 0 ] )
2022-04-29 21:39:42 +08:00
}
pathSelected = true
path = arr [ 1 ]
default :
2022-07-06 17:14:06 +08:00
return define . BuildOutputOption { } , fmt . Errorf ( "unrecognized key %q in build output option: %q" , arr [ 0 ] , buildOutput )
2022-04-29 21:39:42 +08:00
}
}
if ! typeSelected || ! pathSelected {
return define . BuildOutputOption { } , fmt . Errorf ( "invalid build output option %q, accepted keys are type and dest must be present" , buildOutput )
}
if path == "-" {
if isDir {
return define . BuildOutputOption { } , fmt . Errorf ( "invalid build output option %q, type=local and dest=- is not supported" , buildOutput )
}
2024-08-16 00:50:07 +08:00
return define . BuildOutputOption {
Path : "" ,
2022-04-29 21:39:42 +08:00
IsDir : false ,
2024-08-16 00:50:07 +08:00
IsStdout : true ,
} , nil
2022-04-29 21:39:42 +08:00
}
return define . BuildOutputOption { Path : path , IsDir : isDir , IsStdout : isStdout } , nil
}
2023-11-14 05:58:24 +08:00
// TeeType parses a string value and returns a TeeType
func TeeType ( teeType string ) define . TeeType {
return define . TeeType ( strings . ToLower ( teeType ) )
}
2023-07-18 04:27:19 +08:00
// GetConfidentialWorkloadOptions parses a confidential workload settings
// argument, which controls both whether or not we produce an image that
// expects to be run using krun, and how we handle things like encrypting
// the disk image that the container image will contain.
func GetConfidentialWorkloadOptions ( arg string ) ( define . ConfidentialWorkloadOptions , error ) {
options := define . ConfidentialWorkloadOptions {
TempDir : GetTempDir ( ) ,
}
defaults := options
for _ , option := range strings . Split ( arg , "," ) {
var err error
switch {
case strings . HasPrefix ( option , "type=" ) :
2023-11-14 05:58:24 +08:00
options . TeeType = TeeType ( strings . TrimPrefix ( option , "type=" ) )
2023-07-18 04:27:19 +08:00
switch options . TeeType {
case define . SEV , define . SNP , mkcwtypes . SEV_NO_ES :
default :
return options , fmt . Errorf ( "parsing type= value %q: unrecognized value" , options . TeeType )
}
case strings . HasPrefix ( option , "attestation_url=" ) , strings . HasPrefix ( option , "attestation-url=" ) :
options . Convert = true
options . AttestationURL = strings . TrimPrefix ( option , "attestation_url=" )
if options . AttestationURL == option {
options . AttestationURL = strings . TrimPrefix ( option , "attestation-url=" )
}
2024-09-19 15:30:30 +08:00
case strings . HasPrefix ( option , "passphrase=" ) :
2023-07-18 04:27:19 +08:00
options . Convert = true
options . DiskEncryptionPassphrase = strings . TrimPrefix ( option , "passphrase=" )
case strings . HasPrefix ( option , "workload_id=" ) , strings . HasPrefix ( option , "workload-id=" ) :
options . WorkloadID = strings . TrimPrefix ( option , "workload_id=" )
if options . WorkloadID == option {
options . WorkloadID = strings . TrimPrefix ( option , "workload-id=" )
}
case strings . HasPrefix ( option , "cpus=" ) :
options . CPUs , err = strconv . Atoi ( strings . TrimPrefix ( option , "cpus=" ) )
if err != nil {
return options , fmt . Errorf ( "parsing cpus= value %q: %w" , strings . TrimPrefix ( option , "cpus=" ) , err )
}
case strings . HasPrefix ( option , "memory=" ) :
options . Memory , err = strconv . Atoi ( strings . TrimPrefix ( option , "memory=" ) )
if err != nil {
return options , fmt . Errorf ( "parsing memory= value %q: %w" , strings . TrimPrefix ( option , "memorys" ) , err )
}
case option == "ignore_attestation_errors" , option == "ignore-attestation-errors" :
options . IgnoreAttestationErrors = true
case strings . HasPrefix ( option , "ignore_attestation_errors=" ) , strings . HasPrefix ( option , "ignore-attestation-errors=" ) :
val := strings . TrimPrefix ( option , "ignore_attestation_errors=" )
if val == option {
val = strings . TrimPrefix ( option , "ignore-attestation-errors=" )
}
options . IgnoreAttestationErrors = val == "true" || val == "yes" || val == "on" || val == "1"
case strings . HasPrefix ( option , "firmware-library=" ) , strings . HasPrefix ( option , "firmware_library=" ) :
val := strings . TrimPrefix ( option , "firmware-library=" )
if val == option {
val = strings . TrimPrefix ( option , "firmware_library=" )
}
options . FirmwareLibrary = val
case strings . HasPrefix ( option , "slop=" ) :
options . Slop = strings . TrimPrefix ( option , "slop=" )
default :
knownOptions := [ ] string { "type" , "attestation_url" , "passphrase" , "workload_id" , "cpus" , "memory" , "firmware_library" , "slop" }
return options , fmt . Errorf ( "expected one or more of %q as arguments for --cw, not %q" , knownOptions , option )
}
}
if options != defaults && ! options . Convert {
return options , fmt . Errorf ( "--cw arguments missing one or more of (%q, %q)" , "passphrase" , "attestation_url" )
}
return options , nil
}
2023-12-05 03:05:38 +08:00
// SBOMScanOptions parses the build options from the cli
func SBOMScanOptions ( c * cobra . Command ) ( * define . SBOMScanOptions , error ) {
return SBOMScanOptionsFromFlagSet ( c . Flags ( ) , c . Flag )
}
// SBOMScanOptionsFromFlagSet parses scan settings from the cli
2024-08-07 03:07:02 +08:00
func SBOMScanOptionsFromFlagSet ( flags * pflag . FlagSet , _ func ( name string ) * pflag . Flag ) ( * define . SBOMScanOptions , error ) {
2023-12-05 03:05:38 +08:00
preset , err := flags . GetString ( "sbom" )
if err != nil {
return nil , fmt . Errorf ( "invalid value for --sbom: %w" , err )
}
options , err := sbom . Preset ( preset )
if err != nil {
return nil , err
}
if options == nil {
return nil , fmt . Errorf ( "parsing --sbom flag: unrecognized preset name %q" , preset )
}
image , err := flags . GetString ( "sbom-scanner-image" )
if err != nil {
return nil , fmt . Errorf ( "invalid value for --sbom-scanner-image: %w" , err )
}
commands , err := flags . GetStringArray ( "sbom-scanner-command" )
if err != nil {
return nil , fmt . Errorf ( "invalid value for --sbom-scanner-command: %w" , err )
}
mergeStrategy , err := flags . GetString ( "sbom-merge-strategy" )
if err != nil {
return nil , fmt . Errorf ( "invalid value for --sbom-merge-strategy: %w" , err )
}
if image != "" || len ( commands ) > 0 || mergeStrategy != "" {
options = & define . SBOMScanOptions {
Image : image ,
Commands : append ( [ ] string { } , commands ... ) ,
MergeStrategy : define . SBOMMergeStrategy ( mergeStrategy ) ,
}
}
if options . ImageSBOMOutput , err = flags . GetString ( "sbom-image-output" ) ; err != nil {
return nil , fmt . Errorf ( "invalid value for --sbom-image-output: %w" , err )
}
if options . SBOMOutput , err = flags . GetString ( "sbom-output" ) ; err != nil {
return nil , fmt . Errorf ( "invalid value for --sbom-output: %w" , err )
}
if options . ImagePURLOutput , err = flags . GetString ( "sbom-image-purl-output" ) ; err != nil {
return nil , fmt . Errorf ( "invalid value for --sbom-image-purl-output: %w" , err )
}
if options . PURLOutput , err = flags . GetString ( "sbom-purl-output" ) ; err != nil {
return nil , fmt . Errorf ( "invalid value for --sbom-purl-output: %w" , err )
}
2023-12-05 03:05:38 +08:00
if options . Image == "" || len ( options . Commands ) == 0 {
return options , fmt . Errorf ( "sbom configuration missing one or more of (%q or %q)" , "--sbom-scanner-image" , "--sbom-scanner-command" )
}
if options . SBOMOutput == "" && options . ImageSBOMOutput == "" && options . PURLOutput == "" && options . ImagePURLOutput == "" {
return options , fmt . Errorf ( "sbom configuration missing one or more of (%q, %q, %q or %q)" , "--sbom-output" , "--sbom-image-output" , "--sbom-purl-output" , "--sbom-image-purl-output" )
2023-12-05 03:05:38 +08:00
}
if len ( options . Commands ) > 1 && options . MergeStrategy == "" {
return options , fmt . Errorf ( "sbom configuration included multiple %q values but no %q value" , "--sbom-scanner-command" , "--sbom-merge-strategy" )
}
switch options . MergeStrategy {
default :
return options , fmt . Errorf ( "sbom arguments included unrecognized merge strategy %q" , string ( options . MergeStrategy ) )
case define . SBOMMergeStrategyCat , define . SBOMMergeStrategyCycloneDXByComponentNameAndVersion , define . SBOMMergeStrategySPDXByPackageNameAndVersionInfo :
// all good here
}
return options , nil
}
2018-06-16 00:28:03 +08:00
// IDMappingOptions parses the build options related to user namespaces and ID mapping.
2024-08-07 03:07:02 +08:00
func IDMappingOptions ( c * cobra . Command , _ define . Isolation ) ( usernsOptions define . NamespaceOptions , idmapOptions * define . IDMappingOptions , err error ) {
2022-01-13 03:14:46 +08:00
return IDMappingOptionsFromFlagSet ( c . Flags ( ) , c . PersistentFlags ( ) , c . Flag )
}
2022-06-20 15:29:56 +08:00
// GetAutoOptions returns a AutoUserNsOptions with the settings to setup automatically
// a user namespace.
func GetAutoOptions ( base string ) ( * storageTypes . AutoUserNsOptions , error ) {
parts := strings . SplitN ( base , ":" , 2 )
if parts [ 0 ] != "auto" {
2022-07-06 17:14:06 +08:00
return nil , errors . New ( "wrong user namespace mode" )
2022-06-20 15:29:56 +08:00
}
options := storageTypes . AutoUserNsOptions { }
if len ( parts ) == 1 {
return & options , nil
}
for _ , o := range strings . Split ( parts [ 1 ] , "," ) {
v := strings . SplitN ( o , "=" , 2 )
if len ( v ) != 2 {
return nil , fmt . Errorf ( "invalid option specified: %q" , o )
}
switch v [ 0 ] {
case "size" :
s , err := strconv . ParseUint ( v [ 1 ] , 10 , 32 )
if err != nil {
return nil , err
}
options . Size = uint32 ( s )
case "uidmapping" :
mapping , err := storageTypes . ParseIDMapping ( [ ] string { v [ 1 ] } , nil , "" , "" )
if err != nil {
return nil , err
}
options . AdditionalUIDMappings = append ( options . AdditionalUIDMappings , mapping . UIDMap ... )
case "gidmapping" :
mapping , err := storageTypes . ParseIDMapping ( nil , [ ] string { v [ 1 ] } , "" , "" )
if err != nil {
return nil , err
}
options . AdditionalGIDMappings = append ( options . AdditionalGIDMappings , mapping . GIDMap ... )
default :
return nil , fmt . Errorf ( "unknown option specified: %q" , v [ 0 ] )
}
}
return & options , nil
}
2022-01-13 03:14:46 +08:00
// IDMappingOptionsFromFlagSet parses the build options related to user namespaces and ID mapping.
func IDMappingOptionsFromFlagSet ( flags * pflag . FlagSet , persistentFlags * pflag . FlagSet , findFlagFunc func ( name string ) * pflag . Flag ) ( usernsOptions define . NamespaceOptions , idmapOptions * define . IDMappingOptions , err error ) {
2022-06-20 15:29:56 +08:00
isAuto := false
autoOpts := & storageTypes . AutoUserNsOptions { }
2022-01-13 03:14:46 +08:00
user := findFlagFunc ( "userns-uid-map-user" ) . Value . String ( )
group := findFlagFunc ( "userns-gid-map-group" ) . Value . String ( )
2018-06-07 12:45:17 +08:00
// If only the user or group was specified, use the same value for the
// other, since we need both in order to initialize the maps using the
// names.
if user == "" && group != "" {
user = group
}
if group == "" && user != "" {
group = user
}
// Either start with empty maps or the name-based maps.
mappings := idtools . NewIDMappingsFromMaps ( nil , nil )
if user != "" && group != "" {
submappings , err := idtools . NewIDMappings ( user , group )
if err != nil {
return nil , nil , err
}
mappings = submappings
}
2022-01-13 03:14:46 +08:00
globalOptions := persistentFlags
2018-06-07 12:45:17 +08:00
// We'll parse the UID and GID mapping options the same way.
buildIDMap := func ( basemap [ ] idtools . IDMap , option string ) ( [ ] specs . LinuxIDMapping , error ) {
outmap := make ( [ ] specs . LinuxIDMapping , 0 , len ( basemap ) )
// Start with the name-based map entries.
for _ , m := range basemap {
outmap = append ( outmap , specs . LinuxIDMapping {
ContainerID : uint32 ( m . ContainerID ) ,
HostID : uint32 ( m . HostID ) ,
Size : uint32 ( m . Size ) ,
} )
}
// Parse the flag's value as one or more triples (if it's even
// been set), and append them.
2018-06-15 10:03:55 +08:00
var spec [ ] string
2019-01-22 23:35:52 +08:00
if globalOptions . Lookup ( option ) != nil && globalOptions . Lookup ( option ) . Changed {
spec , _ = globalOptions . GetStringSlice ( option )
2018-06-15 10:03:55 +08:00
}
2022-01-13 03:14:46 +08:00
if findFlagFunc ( option ) . Changed {
spec , _ = flags . GetStringSlice ( option )
2018-06-15 10:03:55 +08:00
}
idmap , err := parseIDMap ( spec )
2018-06-07 12:45:17 +08:00
if err != nil {
return nil , err
}
for _ , m := range idmap {
outmap = append ( outmap , specs . LinuxIDMapping {
ContainerID : m [ 0 ] ,
HostID : m [ 1 ] ,
Size : m [ 2 ] ,
} )
}
return outmap , nil
}
uidmap , err := buildIDMap ( mappings . UIDs ( ) , "userns-uid-map" )
if err != nil {
return nil , nil , err
}
gidmap , err := buildIDMap ( mappings . GIDs ( ) , "userns-gid-map" )
if err != nil {
return nil , nil , err
}
// If we only have one map or the other populated at this point, then
// use the same mapping for both, since we know that no user or group
// name was specified, but a specific mapping was for one or the other.
if len ( uidmap ) == 0 && len ( gidmap ) != 0 {
uidmap = gidmap
}
if len ( gidmap ) == 0 && len ( uidmap ) != 0 {
gidmap = uidmap
}
2019-03-08 22:00:20 +08:00
2018-06-07 12:45:17 +08:00
// By default, having mappings configured means we use a user
// namespace. Otherwise, we don't.
2021-02-07 06:49:40 +08:00
usernsOption := define . NamespaceOption {
2018-06-07 12:45:17 +08:00
Name : string ( specs . UserNamespace ) ,
2019-03-20 04:08:02 +08:00
Host : len ( uidmap ) == 0 && len ( gidmap ) == 0 ,
2018-06-07 12:45:17 +08:00
}
// If the user specifically requested that we either use or don't use
// user namespaces, override that default.
2022-01-13 03:14:46 +08:00
if findFlagFunc ( "userns" ) . Changed {
how := findFlagFunc ( "userns" ) . Value . String ( )
2022-06-20 15:29:56 +08:00
if strings . HasPrefix ( how , "auto" ) {
autoOpts , err = GetAutoOptions ( how )
if err != nil {
return nil , nil , err
}
isAuto = true
2018-06-07 12:45:17 +08:00
usernsOption . Host = false
2022-06-20 15:29:56 +08:00
} else {
switch how {
case "" , "container" , "private" :
usernsOption . Host = false
case "host" :
usernsOption . Host = true
default :
how = strings . TrimPrefix ( how , "ns:" )
2024-04-11 16:46:51 +08:00
if err := fileutils . Exists ( how ) ; err != nil {
2022-07-06 17:14:06 +08:00
return nil , nil , fmt . Errorf ( "checking %s namespace: %w" , string ( specs . UserNamespace ) , err )
2022-06-20 15:29:56 +08:00
}
logrus . Debugf ( "setting %q namespace to %q" , string ( specs . UserNamespace ) , how )
usernsOption . Path = how
2018-06-07 12:45:17 +08:00
}
}
}
2021-02-07 06:49:40 +08:00
usernsOptions = define . NamespaceOptions { usernsOption }
2019-01-22 23:35:52 +08:00
2018-06-07 12:45:17 +08:00
// If the user requested that we use the host namespace, but also that
// we use mappings, that's not going to work.
if ( len ( uidmap ) != 0 || len ( gidmap ) != 0 ) && usernsOption . Host {
2022-07-06 17:14:06 +08:00
return nil , nil , fmt . Errorf ( "can not specify ID mappings while using host's user namespace" )
2018-06-07 12:45:17 +08:00
}
2021-02-07 06:49:40 +08:00
return usernsOptions , & define . IDMappingOptions {
2018-06-07 12:45:17 +08:00
HostUIDMapping : usernsOption . Host ,
HostGIDMapping : usernsOption . Host ,
UIDMap : uidmap ,
GIDMap : gidmap ,
2022-06-20 15:29:56 +08:00
AutoUserNs : isAuto ,
AutoUserNsOpts : * autoOpts ,
2018-06-07 12:45:17 +08:00
} , nil
}
func parseIDMap ( spec [ ] string ) ( m [ ] [ 3 ] uint32 , err error ) {
for _ , s := range spec {
args := strings . FieldsFunc ( s , func ( r rune ) bool { return ! unicode . IsDigit ( r ) } )
if len ( args ) % 3 != 0 {
2022-07-06 17:14:06 +08:00
return nil , fmt . Errorf ( "mapping %q is not in the form containerid:hostid:size[,...]" , s )
2018-06-07 12:45:17 +08:00
}
for len ( args ) >= 3 {
cid , err := strconv . ParseUint ( args [ 0 ] , 10 , 32 )
if err != nil {
2022-09-18 18:36:08 +08:00
return nil , fmt . Errorf ( "parsing container ID %q from mapping %q as a number: %w" , args [ 0 ] , s , err )
2018-06-07 12:45:17 +08:00
}
hostid , err := strconv . ParseUint ( args [ 1 ] , 10 , 32 )
if err != nil {
2022-09-18 18:36:08 +08:00
return nil , fmt . Errorf ( "parsing host ID %q from mapping %q as a number: %w" , args [ 1 ] , s , err )
2018-06-07 12:45:17 +08:00
}
size , err := strconv . ParseUint ( args [ 2 ] , 10 , 32 )
if err != nil {
2022-09-18 18:36:08 +08:00
return nil , fmt . Errorf ( "parsing %q from mapping %q as a number: %w" , args [ 2 ] , s , err )
2018-06-07 12:45:17 +08:00
}
m = append ( m , [ 3 ] uint32 { uint32 ( cid ) , uint32 ( hostid ) , uint32 ( size ) } )
args = args [ 3 : ]
}
}
return m , nil
}
2018-06-16 00:28:03 +08:00
// NamespaceOptions parses the build options for all namespaces except for user namespace.
2021-02-07 06:49:40 +08:00
func NamespaceOptions ( c * cobra . Command ) ( namespaceOptions define . NamespaceOptions , networkPolicy define . NetworkConfigurationPolicy , err error ) {
2022-01-12 04:29:28 +08:00
return NamespaceOptionsFromFlagSet ( c . Flags ( ) , c . Flag )
}
// NamespaceOptionsFromFlagSet parses the build options for all namespaces except for user namespace.
func NamespaceOptionsFromFlagSet ( flags * pflag . FlagSet , findFlagFunc func ( name string ) * pflag . Flag ) ( namespaceOptions define . NamespaceOptions , networkPolicy define . NetworkConfigurationPolicy , err error ) {
2021-02-07 06:49:40 +08:00
options := make ( define . NamespaceOptions , 0 , 7 )
policy := define . NetworkDefault
2021-11-19 04:20:50 +08:00
for _ , what := range [ ] string { "cgroupns" , string ( specs . IPCNamespace ) , "network" , string ( specs . PIDNamespace ) , string ( specs . UTSNamespace ) } {
2022-01-12 04:29:28 +08:00
if flags . Lookup ( what ) != nil && findFlagFunc ( what ) . Changed {
how := findFlagFunc ( what ) . Value . String ( )
2018-06-07 12:45:17 +08:00
switch what {
2021-11-19 04:20:50 +08:00
case "cgroupns" :
what = string ( specs . CgroupNamespace )
2018-06-07 12:45:17 +08:00
}
switch how {
2020-08-04 22:13:17 +08:00
case "" , "container" , "private" :
2018-06-07 12:45:17 +08:00
logrus . Debugf ( "setting %q namespace to %q" , what , "" )
2021-10-26 16:53:20 +08:00
policy = define . NetworkEnabled
2021-02-07 06:49:40 +08:00
options . AddOrReplace ( define . NamespaceOption {
2018-06-07 12:45:17 +08:00
Name : what ,
} )
case "host" :
logrus . Debugf ( "setting %q namespace to host" , what )
2021-10-26 16:53:20 +08:00
policy = define . NetworkEnabled
2021-02-07 06:49:40 +08:00
options . AddOrReplace ( define . NamespaceOption {
2018-06-07 12:45:17 +08:00
Name : what ,
Host : true ,
} )
default :
2019-07-16 22:47:25 +08:00
if what == string ( specs . NetworkNamespace ) {
2018-06-07 12:45:17 +08:00
if how == "none" {
2021-02-07 06:49:40 +08:00
options . AddOrReplace ( define . NamespaceOption {
2018-06-07 12:45:17 +08:00
Name : what ,
} )
2021-02-07 06:49:40 +08:00
policy = define . NetworkDisabled
2018-06-07 12:45:17 +08:00
logrus . Debugf ( "setting network to disabled" )
break
}
}
2020-09-30 22:13:02 +08:00
how = strings . TrimPrefix ( how , "ns:" )
2022-01-19 23:43:02 +08:00
// if not a path we assume it is a comma separated network list, see setupNamespaces() in run_linux.go
if filepath . IsAbs ( how ) || what != string ( specs . NetworkNamespace ) {
2024-04-11 16:46:51 +08:00
if err := fileutils . Exists ( how ) ; err != nil {
2022-07-06 17:14:06 +08:00
return nil , define . NetworkDefault , fmt . Errorf ( "checking %s namespace: %w" , what , err )
2022-01-19 23:43:02 +08:00
}
2018-06-07 12:45:17 +08:00
}
2021-02-07 06:49:40 +08:00
policy = define . NetworkEnabled
2018-06-07 12:45:17 +08:00
logrus . Debugf ( "setting %q namespace to %q" , what , how )
2021-02-07 06:49:40 +08:00
options . AddOrReplace ( define . NamespaceOption {
2018-06-07 12:45:17 +08:00
Name : what ,
Path : how ,
} )
}
}
}
return options , policy , nil
}
2018-05-12 01:00:14 +08:00
2021-02-07 06:49:40 +08:00
func defaultIsolation ( ) ( define . Isolation , error ) {
2018-05-12 01:08:18 +08:00
isolation , isSet := os . LookupEnv ( "BUILDAH_ISOLATION" )
if isSet {
2018-10-04 14:19:12 +08:00
switch strings . ToLower ( isolation ) {
case "oci" :
2021-02-07 06:49:40 +08:00
return define . IsolationOCI , nil
2018-10-04 14:19:12 +08:00
case "rootless" :
2021-02-07 06:49:40 +08:00
return define . IsolationOCIRootless , nil
2018-10-04 14:19:12 +08:00
case "chroot" :
2021-02-07 06:49:40 +08:00
return define . IsolationChroot , nil
2018-10-04 14:19:12 +08:00
default :
2022-07-06 17:14:06 +08:00
return 0 , fmt . Errorf ( "unrecognized $BUILDAH_ISOLATION value %q" , isolation )
2018-05-12 01:08:18 +08:00
}
2018-05-12 01:00:14 +08:00
}
2020-07-07 22:15:40 +08:00
if unshare . IsRootless ( ) {
2021-02-07 06:49:40 +08:00
return define . IsolationOCIRootless , nil
2020-07-07 22:15:40 +08:00
}
2021-02-07 06:49:40 +08:00
return define . IsolationDefault , nil
2018-05-12 01:00:14 +08:00
}
// IsolationOption parses the --isolation flag.
2021-02-07 06:49:40 +08:00
func IsolationOption ( isolation string ) ( define . Isolation , error ) {
2019-01-22 23:35:52 +08:00
if isolation != "" {
switch strings . ToLower ( isolation ) {
2021-02-23 20:27:24 +08:00
case "oci" , "default" :
2021-02-07 06:49:40 +08:00
return define . IsolationOCI , nil
2018-10-04 14:19:12 +08:00
case "rootless" :
2021-02-07 06:49:40 +08:00
return define . IsolationOCIRootless , nil
2018-10-04 14:19:12 +08:00
case "chroot" :
2021-02-07 06:49:40 +08:00
return define . IsolationChroot , nil
2018-10-04 14:19:12 +08:00
default :
2022-07-06 17:14:06 +08:00
return 0 , fmt . Errorf ( "unrecognized isolation type %q" , isolation )
2018-05-12 01:00:14 +08:00
}
}
2018-05-12 01:08:18 +08:00
return defaultIsolation ( )
2018-05-12 01:00:14 +08:00
}
2019-04-10 03:57:12 +08:00
2019-09-07 03:07:18 +08:00
// Device parses device mapping string to a src, dest & permissions string
2020-12-22 00:19:56 +08:00
// Valid values for device look like:
2022-11-04 19:04:16 +08:00
//
// '/dev/sdc"
// '/dev/sdc:/dev/xvdc"
// '/dev/sdc:/dev/xvdc:rwm"
// '/dev/sdc:rm"
2019-09-07 03:07:18 +08:00
func Device ( device string ) ( string , string , string , error ) {
src := ""
dst := ""
permissions := "rwm"
arr := strings . Split ( device , ":" )
switch len ( arr ) {
case 3 :
if ! isValidDeviceMode ( arr [ 2 ] ) {
2022-07-06 17:14:06 +08:00
return "" , "" , "" , fmt . Errorf ( "invalid device mode: %s" , arr [ 2 ] )
2019-09-07 03:07:18 +08:00
}
permissions = arr [ 2 ]
fallthrough
case 2 :
if isValidDeviceMode ( arr [ 1 ] ) {
permissions = arr [ 1 ]
} else {
if len ( arr [ 1 ] ) == 0 || arr [ 1 ] [ 0 ] != '/' {
2022-07-06 17:14:06 +08:00
return "" , "" , "" , fmt . Errorf ( "invalid device mode: %s" , arr [ 1 ] )
2019-09-07 03:07:18 +08:00
}
dst = arr [ 1 ]
}
fallthrough
case 1 :
if len ( arr [ 0 ] ) > 0 {
src = arr [ 0 ]
break
}
fallthrough
default :
2022-07-06 17:14:06 +08:00
return "" , "" , "" , fmt . Errorf ( "invalid device specification: %s" , device )
2019-09-07 03:07:18 +08:00
}
if dst == "" {
dst = src
}
return src , dst , permissions , nil
}
// isValidDeviceMode checks if the mode for device is valid or not.
// isValid mode is a composition of r (read), w (write), and m (mknod).
func isValidDeviceMode ( mode string ) bool {
2024-08-16 00:50:07 +08:00
legalDeviceMode := map [ rune ] struct { } {
2023-12-31 01:42:31 +08:00
'r' : { } ,
'w' : { } ,
'm' : { } ,
2019-09-07 03:07:18 +08:00
}
if mode == "" {
return false
}
for _ , c := range mode {
2023-12-31 01:42:31 +08:00
if _ , has := legalDeviceMode [ c ] ; ! has {
2019-09-07 03:07:18 +08:00
return false
}
2023-12-31 01:42:31 +08:00
delete ( legalDeviceMode , c )
2019-09-07 03:07:18 +08:00
}
return true
}
2019-12-18 00:01:52 +08:00
2023-11-16 03:20:56 +08:00
// GetTempDir returns the path of the preferred temporary directory on the host.
2019-12-18 00:01:52 +08:00
func GetTempDir ( ) string {
2023-09-12 20:35:12 +08:00
return tmpdir . GetTempDir ( )
2019-12-18 00:01:52 +08:00
}
2021-04-17 06:21:31 +08:00
// Secrets parses the --secret flag
2021-10-22 04:14:05 +08:00
func Secrets ( secrets [ ] string ) ( map [ string ] define . Secret , error ) {
parsed := make ( map [ string ] define . Secret )
2021-04-17 06:21:31 +08:00
for _ , secret := range secrets {
2021-10-22 04:14:05 +08:00
tokens := strings . Split ( secret , "," )
var id , src , typ string
for _ , val := range tokens {
kv := strings . SplitN ( val , "=" , 2 )
switch kv [ 0 ] {
case "id" :
id = kv [ 1 ]
case "src" :
src = kv [ 1 ]
case "env" :
src = kv [ 1 ]
typ = "env"
case "type" :
if kv [ 1 ] != "file" && kv [ 1 ] != "env" {
return nil , errors . New ( "invalid secret type, must be file or env" )
}
typ = kv [ 1 ]
2024-10-17 05:09:41 +08:00
default :
return nil , errInvalidSecretSyntax
2021-10-22 04:14:05 +08:00
}
}
if id == "" {
2024-10-17 05:09:41 +08:00
return nil , errInvalidSecretSyntax
2021-04-17 06:21:31 +08:00
}
2021-10-22 04:14:05 +08:00
if src == "" {
src = id
}
if typ == "" {
if _ , ok := os . LookupEnv ( id ) ; ok {
typ = "env"
2021-04-17 06:21:31 +08:00
} else {
2021-10-22 04:14:05 +08:00
typ = "file"
2021-04-17 06:21:31 +08:00
}
}
2021-10-22 04:14:05 +08:00
if typ == "file" {
fullPath , err := filepath . Abs ( src )
if err != nil {
2022-07-06 17:14:06 +08:00
return nil , fmt . Errorf ( "could not parse secrets: %w" , err )
2021-10-22 04:14:05 +08:00
}
2024-04-11 16:46:51 +08:00
err = fileutils . Exists ( fullPath )
2021-10-22 04:14:05 +08:00
if err != nil {
2022-07-06 17:14:06 +08:00
return nil , fmt . Errorf ( "could not parse secrets: %w" , err )
2021-10-22 04:14:05 +08:00
}
src = fullPath
}
newSecret := define . Secret {
2024-10-17 05:09:41 +08:00
ID : id ,
2021-10-22 04:14:05 +08:00
Source : src ,
SourceType : typ ,
}
parsed [ id ] = newSecret
2021-04-17 06:21:31 +08:00
}
return parsed , nil
}
2021-07-26 14:07:23 +08:00
// SSH parses the --ssh flag
func SSH ( sshSources [ ] string ) ( map [ string ] * sshagent . Source , error ) {
parsed := make ( map [ string ] * sshagent . Source )
var paths [ ] string
for _ , v := range sshSources {
parts := strings . SplitN ( v , "=" , 2 )
if len ( parts ) > 1 {
paths = strings . Split ( parts [ 1 ] , "," )
}
source , err := sshagent . NewSource ( paths )
if err != nil {
return nil , err
}
parsed [ parts [ 0 ] ] = source
}
return parsed , nil
}
2021-10-07 21:10:22 +08:00
2022-09-13 14:35:34 +08:00
// ContainerIgnoreFile consumes path to `dockerignore` or `containerignore`
// and returns list of files to exclude along with the path to processed ignore
// file. Deprecated since this might become internal only, please avoid relying
// on this function.
func ContainerIgnoreFile ( contextDir , path string , containerFiles [ ] string ) ( [ ] string , string , error ) {
2021-10-07 21:10:22 +08:00
if path != "" {
excludes , err := imagebuilder . ParseIgnore ( path )
return excludes , path , err
}
2022-09-13 14:35:34 +08:00
// If path was not supplied give priority to `<containerfile>.containerignore` first.
for _ , containerfile := range containerFiles {
if ! filepath . IsAbs ( containerfile ) {
containerfile = filepath . Join ( contextDir , containerfile )
}
containerfileIgnore := ""
2024-04-11 16:46:51 +08:00
if err := fileutils . Exists ( containerfile + ".containerignore" ) ; err == nil {
2022-09-13 14:35:34 +08:00
containerfileIgnore = containerfile + ".containerignore"
}
2024-04-11 16:46:51 +08:00
if err := fileutils . Exists ( containerfile + ".dockerignore" ) ; err == nil {
2022-09-13 14:35:34 +08:00
containerfileIgnore = containerfile + ".dockerignore"
}
if containerfileIgnore != "" {
excludes , err := imagebuilder . ParseIgnore ( containerfileIgnore )
return excludes , containerfileIgnore , err
}
}
2022-12-15 20:20:03 +08:00
path , symlinkErr := securejoin . SecureJoin ( contextDir , ".containerignore" )
if symlinkErr != nil {
return nil , "" , symlinkErr
}
2021-10-07 21:10:22 +08:00
excludes , err := imagebuilder . ParseIgnore ( path )
2022-07-27 03:27:30 +08:00
if errors . Is ( err , os . ErrNotExist ) {
2022-12-15 20:20:03 +08:00
path , symlinkErr = securejoin . SecureJoin ( contextDir , ".dockerignore" )
if symlinkErr != nil {
return nil , "" , symlinkErr
}
2021-10-07 21:10:22 +08:00
excludes , err = imagebuilder . ParseIgnore ( path )
}
2022-07-27 03:27:30 +08:00
if errors . Is ( err , os . ErrNotExist ) {
2021-10-07 21:10:22 +08:00
return excludes , "" , nil
}
return excludes , path , err
}