summaryrefslogtreecommitdiff
path: root/vendor/github.com/projectatomic/buildah/pkg/parse/parse.go
diff options
context:
space:
mode:
authorDaniel J Walsh <dwalsh@redhat.com>2018-09-18 15:31:54 -0400
committerDaniel J Walsh <dwalsh@redhat.com>2018-09-18 17:20:30 -0400
commit92b28a88d8bcd5aa50352ecaff844229df1cee59 (patch)
treeb340ddc09d29ae2cf29cb83269bcb614d94a6a10 /vendor/github.com/projectatomic/buildah/pkg/parse/parse.go
parentc3a0874222784e8996dbc472b9ca893a80aff451 (diff)
downloadpodman-92b28a88d8bcd5aa50352ecaff844229df1cee59.tar.gz
podman-92b28a88d8bcd5aa50352ecaff844229df1cee59.tar.bz2
podman-92b28a88d8bcd5aa50352ecaff844229df1cee59.zip
Vendor in latest containers/buildah
Switch from projectatomic/buildah to containers/buildah Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
Diffstat (limited to 'vendor/github.com/projectatomic/buildah/pkg/parse/parse.go')
-rw-r--r--vendor/github.com/projectatomic/buildah/pkg/parse/parse.go572
1 files changed, 0 insertions, 572 deletions
diff --git a/vendor/github.com/projectatomic/buildah/pkg/parse/parse.go b/vendor/github.com/projectatomic/buildah/pkg/parse/parse.go
deleted file mode 100644
index 2dff18818..000000000
--- a/vendor/github.com/projectatomic/buildah/pkg/parse/parse.go
+++ /dev/null
@@ -1,572 +0,0 @@
-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 (
- "fmt"
- "net"
- "os"
- "path/filepath"
- "reflect"
- "regexp"
- "strconv"
- "strings"
- "unicode"
-
- "github.com/containers/image/types"
- "github.com/containers/storage/pkg/idtools"
- "github.com/docker/go-units"
- "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
- "github.com/projectatomic/buildah"
- "github.com/sirupsen/logrus"
- "github.com/urfave/cli"
- "golang.org/x/crypto/ssh/terminal"
- "golang.org/x/sys/unix"
-)
-
-const (
- // SeccompDefaultPath defines the default seccomp path
- SeccompDefaultPath = "/usr/share/containers/seccomp.json"
- // SeccompOverridePath if this exists it overrides the default seccomp path
- SeccompOverridePath = "/etc/crio/seccomp.json"
-)
-
-// CommonBuildOptions parses the build options from the bud cli
-func CommonBuildOptions(c *cli.Context) (*buildah.CommonBuildOptions, error) {
- var (
- memoryLimit int64
- memorySwap int64
- err error
- )
- rlim := unix.Rlimit{Cur: 1048576, Max: 1048576}
- defaultLimits := []string{}
- if err := unix.Setrlimit(unix.RLIMIT_NOFILE, &rlim); err == nil {
- defaultLimits = append(defaultLimits, fmt.Sprintf("nofile=%d:%d", rlim.Cur, rlim.Max))
- }
- if err := unix.Setrlimit(unix.RLIMIT_NPROC, &rlim); err == nil {
- defaultLimits = append(defaultLimits, fmt.Sprintf("nproc=%d:%d", rlim.Cur, rlim.Max))
- }
- if c.String("memory") != "" {
- memoryLimit, err = units.RAMInBytes(c.String("memory"))
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for memory")
- }
- }
- if c.String("memory-swap") != "" {
- memorySwap, err = units.RAMInBytes(c.String("memory-swap"))
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for memory-swap")
- }
- }
- if len(c.StringSlice("add-host")) > 0 {
- for _, host := range c.StringSlice("add-host") {
- if err := validateExtraHost(host); err != nil {
- return nil, errors.Wrapf(err, "invalid value for add-host")
- }
- }
- }
- if _, err := units.FromHumanSize(c.String("shm-size")); err != nil {
- return nil, errors.Wrapf(err, "invalid --shm-size")
- }
- if err := ParseVolumes(c.StringSlice("volume")); err != nil {
- return nil, err
- }
-
- commonOpts := &buildah.CommonBuildOptions{
- AddHost: c.StringSlice("add-host"),
- CgroupParent: c.String("cgroup-parent"),
- CPUPeriod: c.Uint64("cpu-period"),
- CPUQuota: c.Int64("cpu-quota"),
- CPUSetCPUs: c.String("cpuset-cpus"),
- CPUSetMems: c.String("cpuset-mems"),
- CPUShares: c.Uint64("cpu-shares"),
- Memory: memoryLimit,
- MemorySwap: memorySwap,
- ShmSize: c.String("shm-size"),
- Ulimit: append(defaultLimits, c.StringSlice("ulimit")...),
- Volumes: c.StringSlice("volume"),
- }
- if err := parseSecurityOpts(c.StringSlice("security-opt"), commonOpts); err != nil {
- return nil, err
- }
- return commonOpts, nil
-}
-
-func parseSecurityOpts(securityOpts []string, commonOpts *buildah.CommonBuildOptions) error {
- for _, opt := range securityOpts {
- if opt == "no-new-privileges" {
- return errors.Errorf("no-new-privileges is not supported")
- }
- con := strings.SplitN(opt, "=", 2)
- if len(con) != 2 {
- return errors.Errorf("Invalid --security-opt name=value pair: %q", opt)
- }
-
- switch con[0] {
- case "label":
- commonOpts.LabelOpts = append(commonOpts.LabelOpts, con[1])
- case "apparmor":
- commonOpts.ApparmorProfile = con[1]
- case "seccomp":
- commonOpts.SeccompProfilePath = con[1]
- default:
- return errors.Errorf("Invalid --security-opt 2: %q", opt)
- }
-
- }
-
- if commonOpts.SeccompProfilePath == "" {
- if _, err := os.Stat(SeccompOverridePath); err == nil {
- commonOpts.SeccompProfilePath = SeccompOverridePath
- } else {
- if !os.IsNotExist(err) {
- return errors.Wrapf(err, "can't check if %q exists", SeccompOverridePath)
- }
- if _, err := os.Stat(SeccompDefaultPath); err != nil {
- if !os.IsNotExist(err) {
- return errors.Wrapf(err, "can't check if %q exists", SeccompDefaultPath)
- }
- } else {
- commonOpts.SeccompProfilePath = SeccompDefaultPath
- }
- }
- }
- return nil
-}
-
-// ParseVolumes validates the host and container paths passed in to the --volume flag
-func ParseVolumes(volumes []string) error {
- if len(volumes) == 0 {
- return nil
- }
- for _, volume := range volumes {
- arr := strings.SplitN(volume, ":", 3)
- if len(arr) < 2 {
- return errors.Errorf("incorrect volume format %q, should be host-dir:ctr-dir[:option]", volume)
- }
- if err := validateVolumeHostDir(arr[0]); err != nil {
- return err
- }
- if err := validateVolumeCtrDir(arr[1]); err != nil {
- return err
- }
- if len(arr) > 2 {
- if err := validateVolumeOpts(arr[2]); err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-func validateVolumeHostDir(hostDir string) error {
- if !filepath.IsAbs(hostDir) {
- return errors.Errorf("invalid host path, must be an absolute path %q", hostDir)
- }
- if _, err := os.Stat(hostDir); err != nil {
- return errors.Wrapf(err, "error checking path %q", hostDir)
- }
- return nil
-}
-
-func validateVolumeCtrDir(ctrDir string) error {
- if !filepath.IsAbs(ctrDir) {
- return errors.Errorf("invalid container path, must be an absolute path %q", ctrDir)
- }
- return nil
-}
-
-func validateVolumeOpts(option string) error {
- var foundRootPropagation, foundRWRO, foundLabelChange int
- options := strings.Split(option, ",")
- for _, opt := range options {
- switch opt {
- case "rw", "ro":
- if foundRWRO > 1 {
- return errors.Errorf("invalid options %q, can only specify 1 'rw' or 'ro' option", option)
- }
- foundRWRO++
- case "z", "Z":
- if foundLabelChange > 1 {
- return errors.Errorf("invalid options %q, can only specify 1 'z' or 'Z' option", option)
- }
- foundLabelChange++
- case "private", "rprivate", "shared", "rshared", "slave", "rslave", "unbindable", "runbindable":
- if foundRootPropagation > 1 {
- return errors.Errorf("invalid options %q, can only specify 1 '[r]shared', '[r]private', '[r]slave' or '[r]unbindable' option", option)
- }
- foundRootPropagation++
- default:
- return errors.Errorf("invalid option type %q", option)
- }
- }
- return nil
-}
-
-// 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 {
- return fmt.Errorf("bad format for add-host: %q", val)
- }
- if _, err := validateIPAddress(arr[1]); err != nil {
- return fmt.Errorf("invalid IP address in add-host: %q", arr[1])
- }
- return nil
-}
-
-// validateIPAddress validates an Ip address.
-// for dns, ip, and ip6 flags also
-func validateIPAddress(val string) (string, error) {
- var ip = net.ParseIP(strings.TrimSpace(val))
- if ip != nil {
- return ip.String(), nil
- }
- return "", fmt.Errorf("%s is not an ip address", val)
-}
-
-// ValidateFlags searches for StringFlags or StringSlice flags that never had
-// a value set. This commonly occurs when the CLI mistakenly takes the next
-// option and uses it as a value.
-func ValidateFlags(c *cli.Context, flags []cli.Flag) error {
- re, err := regexp.Compile("^-.+")
- if err != nil {
- return errors.Wrap(err, "compiling regex failed")
- }
-
- // The --cmd flag can have a following command i.e. --cmd="--help".
- // Let's skip this check just for the --cmd flag.
- for _, flag := range flags {
- switch reflect.TypeOf(flag).String() {
- case "cli.StringSliceFlag":
- {
- f := flag.(cli.StringSliceFlag)
- name := strings.Split(f.Name, ",")
- if f.Name == "cmd" {
- continue
- }
- val := c.StringSlice(name[0])
- for _, v := range val {
- if ok := re.MatchString(v); ok {
- return errors.Errorf("option --%s requires a value", name[0])
- }
- }
- }
- case "cli.StringFlag":
- {
- f := flag.(cli.StringFlag)
- name := strings.Split(f.Name, ",")
- if f.Name == "cmd" {
- continue
- }
- val := c.String(name[0])
- if ok := re.MatchString(val); ok {
- return errors.Errorf("option --%s requires a value", name[0])
- }
- }
- }
- }
- return nil
-}
-
-// SystemContextFromOptions returns a SystemContext populated with values
-// per the input parameters provided by the caller for the use in authentication.
-func SystemContextFromOptions(c *cli.Context) (*types.SystemContext, error) {
- ctx := &types.SystemContext{
- DockerCertPath: c.String("cert-dir"),
- }
- if c.IsSet("tls-verify") {
- ctx.DockerInsecureSkipTLSVerify = !c.BoolT("tls-verify")
- }
- if c.IsSet("creds") {
- var err error
- ctx.DockerAuthConfig, err = getDockerAuth(c.String("creds"))
- if err != nil {
- return nil, err
- }
- }
- if c.IsSet("signature-policy") {
- ctx.SignaturePolicyPath = c.String("signature-policy")
- }
- if c.IsSet("authfile") {
- ctx.AuthFilePath = c.String("authfile")
- }
- if c.GlobalIsSet("registries-conf") {
- ctx.SystemRegistriesConfPath = c.GlobalString("registries-conf")
- }
- if c.GlobalIsSet("registries-conf-dir") {
- ctx.RegistriesDirPath = c.GlobalString("registries-conf-dir")
- }
- ctx.DockerRegistryUserAgent = fmt.Sprintf("Buildah/%s", buildah.Version)
- return ctx, nil
-}
-
-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]
-}
-
-func getDockerAuth(creds string) (*types.DockerAuthConfig, error) {
- username, password := parseCreds(creds)
- if username == "" {
- fmt.Print("Username: ")
- fmt.Scanln(&username)
- }
- if password == "" {
- fmt.Print("Password: ")
- termPassword, err := terminal.ReadPassword(0)
- if err != nil {
- return nil, errors.Wrapf(err, "could not read password from terminal")
- }
- password = string(termPassword)
- }
-
- return &types.DockerAuthConfig{
- Username: username,
- Password: password,
- }, nil
-}
-
-// IDMappingOptions parses the build options related to user namespaces and ID mapping.
-func IDMappingOptions(c *cli.Context) (usernsOptions buildah.NamespaceOptions, idmapOptions *buildah.IDMappingOptions, err error) {
- user := c.String("userns-uid-map-user")
- group := c.String("userns-gid-map-group")
- // 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
- }
- // 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.
- var spec []string
- if c.GlobalIsSet(option) {
- spec = c.GlobalStringSlice(option)
- }
- if c.IsSet(option) {
- spec = c.StringSlice(option)
- }
- idmap, err := parseIDMap(spec)
- 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
- }
- // By default, having mappings configured means we use a user
- // namespace. Otherwise, we don't.
- usernsOption := buildah.NamespaceOption{
- Name: string(specs.UserNamespace),
- Host: len(uidmap) == 0 && len(gidmap) == 0,
- }
- // If the user specifically requested that we either use or don't use
- // user namespaces, override that default.
- if c.IsSet("userns") {
- how := c.String("userns")
- switch how {
- case "", "container":
- usernsOption.Host = false
- case "host":
- usernsOption.Host = true
- default:
- if _, err := os.Stat(how); err != nil {
- return nil, nil, errors.Wrapf(err, "error checking for %s namespace at %q", string(specs.UserNamespace), how)
- }
- logrus.Debugf("setting %q namespace to %q", string(specs.UserNamespace), how)
- usernsOption.Path = how
- }
- }
- usernsOptions = buildah.NamespaceOptions{usernsOption}
- if !c.IsSet("net") {
- usernsOptions = append(usernsOptions, buildah.NamespaceOption{
- Name: string(specs.NetworkNamespace),
- Host: usernsOption.Host,
- })
- }
- // 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 {
- return nil, nil, errors.Errorf("can not specify ID mappings while using host's user namespace")
- }
- return usernsOptions, &buildah.IDMappingOptions{
- HostUIDMapping: usernsOption.Host,
- HostGIDMapping: usernsOption.Host,
- UIDMap: uidmap,
- GIDMap: gidmap,
- }, 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 {
- return nil, fmt.Errorf("mapping %q is not in the form containerid:hostid:size[,...]", s)
- }
- for len(args) >= 3 {
- cid, err := strconv.ParseUint(args[0], 10, 32)
- if err != nil {
- return nil, fmt.Errorf("error parsing container ID %q from mapping %q as a number: %v", args[0], s, err)
- }
- hostid, err := strconv.ParseUint(args[1], 10, 32)
- if err != nil {
- return nil, fmt.Errorf("error parsing host ID %q from mapping %q as a number: %v", args[1], s, err)
- }
- size, err := strconv.ParseUint(args[2], 10, 32)
- if err != nil {
- return nil, fmt.Errorf("error parsing %q from mapping %q as a number: %v", args[2], s, err)
- }
- m = append(m, [3]uint32{uint32(cid), uint32(hostid), uint32(size)})
- args = args[3:]
- }
- }
- return m, nil
-}
-
-// NamespaceOptions parses the build options for all namespaces except for user namespace.
-func NamespaceOptions(c *cli.Context) (namespaceOptions buildah.NamespaceOptions, networkPolicy buildah.NetworkConfigurationPolicy, err error) {
- options := make(buildah.NamespaceOptions, 0, 7)
- policy := buildah.NetworkDefault
- for _, what := range []string{string(specs.IPCNamespace), "net", string(specs.PIDNamespace), string(specs.UTSNamespace)} {
- if c.IsSet(what) {
- how := c.String(what)
- switch what {
- case "net", "network":
- what = string(specs.NetworkNamespace)
- }
- switch how {
- case "", "container":
- logrus.Debugf("setting %q namespace to %q", what, "")
- options.AddOrReplace(buildah.NamespaceOption{
- Name: what,
- })
- case "host":
- logrus.Debugf("setting %q namespace to host", what)
- options.AddOrReplace(buildah.NamespaceOption{
- Name: what,
- Host: true,
- })
- default:
- if what == specs.NetworkNamespace {
- if how == "none" {
- options.AddOrReplace(buildah.NamespaceOption{
- Name: what,
- })
- policy = buildah.NetworkDisabled
- logrus.Debugf("setting network to disabled")
- break
- }
- if !filepath.IsAbs(how) {
- options.AddOrReplace(buildah.NamespaceOption{
- Name: what,
- Path: how,
- })
- policy = buildah.NetworkEnabled
- logrus.Debugf("setting network configuration to %q", how)
- break
- }
- }
- if _, err := os.Stat(how); err != nil {
- return nil, buildah.NetworkDefault, errors.Wrapf(err, "error checking for %s namespace at %q", what, how)
- }
- logrus.Debugf("setting %q namespace to %q", what, how)
- options.AddOrReplace(buildah.NamespaceOption{
- Name: what,
- Path: how,
- })
- }
- }
- }
- return options, policy, nil
-}
-
-func defaultIsolation() (buildah.Isolation, error) {
- isolation, isSet := os.LookupEnv("BUILDAH_ISOLATION")
- if isSet {
- if strings.HasPrefix(strings.ToLower(isolation), "oci") {
- return buildah.IsolationOCI, nil
- } else if strings.HasPrefix(strings.ToLower(isolation), "rootless") {
- return buildah.IsolationOCIRootless, nil
- } else if strings.HasPrefix(strings.ToLower(isolation), "chroot") {
- return buildah.IsolationChroot, nil
- }
- return 0, errors.Errorf("unrecognized $BUILDAH_ISOLATION value %q", isolation)
- }
- return buildah.IsolationDefault, nil
-}
-
-// IsolationOption parses the --isolation flag.
-func IsolationOption(c *cli.Context) (buildah.Isolation, error) {
- if c.String("isolation") != "" {
- if strings.HasPrefix(strings.ToLower(c.String("isolation")), "oci") {
- return buildah.IsolationOCI, nil
- } else if strings.HasPrefix(strings.ToLower(c.String("isolation")), "rootless") {
- return buildah.IsolationOCIRootless, nil
- } else if strings.HasPrefix(strings.ToLower(c.String("isolation")), "chroot") {
- return buildah.IsolationChroot, nil
- } else {
- return buildah.IsolationDefault, errors.Errorf("unrecognized isolation type %q", c.String("isolation"))
- }
- }
- return defaultIsolation()
-}