Merge pull request #8954 from baude/reducebindingsize
Reduce general binding binary size
This commit is contained in:
		
						commit
						2b0cf7728d
					
				| 
						 | 
				
			
			@ -5,7 +5,7 @@ import (
 | 
			
		|||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/containers/buildah/pkg/parse"
 | 
			
		||||
	"github.com/containers/common/pkg/parse"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/specgen"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/util"
 | 
			
		||||
	spec "github.com/opencontainers/runtime-spec/specs-go"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,9 +4,8 @@ import (
 | 
			
		|||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/domain/entities"
 | 
			
		||||
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/api/handlers/utils"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/errorhandling"
 | 
			
		||||
	log "github.com/sirupsen/logrus"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -14,5 +13,5 @@ func UnsupportedHandler(w http.ResponseWriter, r *http.Request) {
 | 
			
		|||
	msg := fmt.Sprintf("Path %s is not supported", r.URL.Path)
 | 
			
		||||
	log.Infof("Request Failed: %s", msg)
 | 
			
		||||
 | 
			
		||||
	utils.WriteJSON(w, http.StatusNotFound, entities.ErrorModel{Message: msg})
 | 
			
		||||
	utils.WriteJSON(w, http.StatusNotFound, errorhandling.ErrorModel{Message: msg})
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@ import (
 | 
			
		|||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"github.com/containers/podman/v2/libpod/define"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/domain/entities"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/errorhandling"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	log "github.com/sirupsen/logrus"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -24,7 +24,7 @@ var (
 | 
			
		|||
func Error(w http.ResponseWriter, apiMessage string, code int, err error) {
 | 
			
		||||
	// Log detailed message of what happened to machine running podman service
 | 
			
		||||
	log.Infof("Request Failed(%s): %s", http.StatusText(code), err.Error())
 | 
			
		||||
	em := entities.ErrorModel{
 | 
			
		||||
	em := errorhandling.ErrorModel{
 | 
			
		||||
		Because:      (errors.Cause(err)).Error(),
 | 
			
		||||
		Message:      err.Error(),
 | 
			
		||||
		ResponseCode: code,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ import (
 | 
			
		|||
	"github.com/containers/podman/v2/libpod/define"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/domain/entities"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/domain/entities/reports"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/errorhandling"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// No such image
 | 
			
		||||
| 
						 | 
				
			
			@ -12,7 +13,7 @@ import (
 | 
			
		|||
type swagErrNoSuchImage struct {
 | 
			
		||||
	// in:body
 | 
			
		||||
	Body struct {
 | 
			
		||||
		entities.ErrorModel
 | 
			
		||||
		errorhandling.ErrorModel
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +22,7 @@ type swagErrNoSuchImage struct {
 | 
			
		|||
type swagErrNoSuchContainer struct {
 | 
			
		||||
	// in:body
 | 
			
		||||
	Body struct {
 | 
			
		||||
		entities.ErrorModel
 | 
			
		||||
		errorhandling.ErrorModel
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +31,7 @@ type swagErrNoSuchContainer struct {
 | 
			
		|||
type swagErrNoSuchNetwork struct {
 | 
			
		||||
	// in:body
 | 
			
		||||
	Body struct {
 | 
			
		||||
		entities.ErrorModel
 | 
			
		||||
		errorhandling.ErrorModel
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +40,7 @@ type swagErrNoSuchNetwork struct {
 | 
			
		|||
type swagErrNoSuchExecInstance struct {
 | 
			
		||||
	// in:body
 | 
			
		||||
	Body struct {
 | 
			
		||||
		entities.ErrorModel
 | 
			
		||||
		errorhandling.ErrorModel
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +49,7 @@ type swagErrNoSuchExecInstance struct {
 | 
			
		|||
type swagErrNoSuchVolume struct {
 | 
			
		||||
	// in:body
 | 
			
		||||
	Body struct {
 | 
			
		||||
		entities.ErrorModel
 | 
			
		||||
		errorhandling.ErrorModel
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -57,7 +58,7 @@ type swagErrNoSuchVolume struct {
 | 
			
		|||
type swagErrNoSuchPod struct {
 | 
			
		||||
	// in:body
 | 
			
		||||
	Body struct {
 | 
			
		||||
		entities.ErrorModel
 | 
			
		||||
		errorhandling.ErrorModel
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -66,7 +67,7 @@ type swagErrNoSuchPod struct {
 | 
			
		|||
type swagErrNoSuchManifest struct {
 | 
			
		||||
	// in:body
 | 
			
		||||
	Body struct {
 | 
			
		||||
		entities.ErrorModel
 | 
			
		||||
		errorhandling.ErrorModel
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -75,7 +76,7 @@ type swagErrNoSuchManifest struct {
 | 
			
		|||
type swagInternalError struct {
 | 
			
		||||
	// in:body
 | 
			
		||||
	Body struct {
 | 
			
		||||
		entities.ErrorModel
 | 
			
		||||
		errorhandling.ErrorModel
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +85,7 @@ type swagInternalError struct {
 | 
			
		|||
type swagConflictError struct {
 | 
			
		||||
	// in:body
 | 
			
		||||
	Body struct {
 | 
			
		||||
		entities.ErrorModel
 | 
			
		||||
		errorhandling.ErrorModel
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +94,7 @@ type swagConflictError struct {
 | 
			
		|||
type swagBadParamError struct {
 | 
			
		||||
	// in:body
 | 
			
		||||
	Body struct {
 | 
			
		||||
		entities.ErrorModel
 | 
			
		||||
		errorhandling.ErrorModel
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +103,7 @@ type swagBadParamError struct {
 | 
			
		|||
type swagContainerAlreadyStartedError struct {
 | 
			
		||||
	// in:body
 | 
			
		||||
	Body struct {
 | 
			
		||||
		entities.ErrorModel
 | 
			
		||||
		errorhandling.ErrorModel
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -111,7 +112,7 @@ type swagContainerAlreadyStartedError struct {
 | 
			
		|||
type swagContainerAlreadyStopped struct {
 | 
			
		||||
	// in:body
 | 
			
		||||
	Body struct {
 | 
			
		||||
		entities.ErrorModel
 | 
			
		||||
		errorhandling.ErrorModel
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -120,7 +121,7 @@ type swagContainerAlreadyStopped struct {
 | 
			
		|||
type swagPodAlreadyStartedError struct {
 | 
			
		||||
	// in:body
 | 
			
		||||
	Body struct {
 | 
			
		||||
		entities.ErrorModel
 | 
			
		||||
		errorhandling.ErrorModel
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -129,7 +130,7 @@ type swagPodAlreadyStartedError struct {
 | 
			
		|||
type swagPodAlreadyStopped struct {
 | 
			
		||||
	// in:body
 | 
			
		||||
	Body struct {
 | 
			
		||||
		entities.ErrorModel
 | 
			
		||||
		errorhandling.ErrorModel
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@ import (
 | 
			
		|||
	"encoding/json"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/domain/entities"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/errorhandling"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ var (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
func handleError(data []byte) error {
 | 
			
		||||
	e := entities.ErrorModel{}
 | 
			
		||||
	e := errorhandling.ErrorModel{}
 | 
			
		||||
	if err := json.Unmarshal(data, &e); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +36,7 @@ func (a APIResponse) Process(unmarshalInto interface{}) error {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func CheckResponseCode(inError error) (int, error) {
 | 
			
		||||
	e, ok := inError.(entities.ErrorModel)
 | 
			
		||||
	e, ok := inError.(errorhandling.ErrorModel)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return -1, errors.New("error is not type ErrorModel")
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
package entities
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"net"
 | 
			
		||||
 | 
			
		||||
	"github.com/containers/buildah/imagebuildah"
 | 
			
		||||
| 
						 | 
				
			
			@ -90,29 +89,6 @@ type ContainerCreateResponse struct {
 | 
			
		|||
	Warnings []string `json:"Warnings"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ErrorModel struct {
 | 
			
		||||
	// API root cause formatted for automated parsing
 | 
			
		||||
	// example: API root cause
 | 
			
		||||
	Because string `json:"cause"`
 | 
			
		||||
	// human error message, formatted for a human to read
 | 
			
		||||
	// example: human error message
 | 
			
		||||
	Message string `json:"message"`
 | 
			
		||||
	// http response code
 | 
			
		||||
	ResponseCode int `json:"response"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrorModel) Error() string {
 | 
			
		||||
	return e.Message
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrorModel) Cause() error {
 | 
			
		||||
	return errors.New(e.Because)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrorModel) Code() int {
 | 
			
		||||
	return e.ResponseCode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BuildOptions describe the options for building container images.
 | 
			
		||||
type BuildOptions struct {
 | 
			
		||||
	imagebuildah.BuildOptions
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -211,7 +211,7 @@ func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []st
 | 
			
		|||
	for _, name := range namesOrIds {
 | 
			
		||||
		inspect, err := containers.Inspect(ic.ClientCtx, name, options)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			errModel, ok := err.(entities.ErrorModel)
 | 
			
		||||
			errModel, ok := err.(errorhandling.ErrorModel)
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return nil, nil, err
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,16 +8,15 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/containers/podman/v2/libpod/image"
 | 
			
		||||
 | 
			
		||||
	"github.com/containers/image/v5/types"
 | 
			
		||||
 | 
			
		||||
	"github.com/containers/common/pkg/config"
 | 
			
		||||
	"github.com/containers/image/v5/docker/reference"
 | 
			
		||||
	"github.com/containers/image/v5/types"
 | 
			
		||||
	"github.com/containers/podman/v2/libpod/image"
 | 
			
		||||
	images "github.com/containers/podman/v2/pkg/bindings/images"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/domain/entities"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/domain/entities/reports"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/domain/utils"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/errorhandling"
 | 
			
		||||
	utils2 "github.com/containers/podman/v2/utils"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -187,7 +186,7 @@ func (ir *ImageEngine) Inspect(ctx context.Context, namesOrIDs []string, opts en
 | 
			
		|||
	for _, i := range namesOrIDs {
 | 
			
		||||
		r, err := images.GetImage(ir.ClientCtx, i, options)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			errModel, ok := err.(entities.ErrorModel)
 | 
			
		||||
			errModel, ok := err.(errorhandling.ErrorModel)
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return nil, nil, err
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ import (
 | 
			
		|||
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/bindings/network"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/domain/entities"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/errorhandling"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +23,7 @@ func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []stri
 | 
			
		|||
	for _, name := range namesOrIds {
 | 
			
		||||
		report, err := network.Inspect(ic.ClientCtx, name, options)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			errModel, ok := err.(entities.ErrorModel)
 | 
			
		||||
			errModel, ok := err.(errorhandling.ErrorModel)
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return nil, nil, err
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@ import (
 | 
			
		|||
	"github.com/containers/podman/v2/pkg/bindings/volumes"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/domain/entities"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/domain/entities/reports"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/errorhandling"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -55,7 +56,7 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin
 | 
			
		|||
	for _, id := range namesOrIds {
 | 
			
		||||
		data, err := volumes.Inspect(ic.ClientCtx, id, nil)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			errModel, ok := err.(entities.ErrorModel)
 | 
			
		||||
			errModel, ok := err.(errorhandling.ErrorModel)
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return nil, nil, err
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -70,3 +70,27 @@ func CloseQuiet(f *os.File) {
 | 
			
		|||
func Contains(err error, sub error) bool {
 | 
			
		||||
	return strings.Contains(err.Error(), sub.Error())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrorModel is used in remote connections with podman
 | 
			
		||||
type ErrorModel struct {
 | 
			
		||||
	// API root cause formatted for automated parsing
 | 
			
		||||
	// example: API root cause
 | 
			
		||||
	Because string `json:"cause"`
 | 
			
		||||
	// human error message, formatted for a human to read
 | 
			
		||||
	// example: human error message
 | 
			
		||||
	Message string `json:"message"`
 | 
			
		||||
	// http response code
 | 
			
		||||
	ResponseCode int `json:"response"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrorModel) Error() string {
 | 
			
		||||
	return e.Message
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrorModel) Cause() error {
 | 
			
		||||
	return errors.New(e.Because)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrorModel) Code() int {
 | 
			
		||||
	return e.ResponseCode
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@ import (
 | 
			
		|||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/containers/buildah/pkg/parse"
 | 
			
		||||
	"github.com/containers/common/pkg/parse"
 | 
			
		||||
	"github.com/containers/podman/v2/libpod/image"
 | 
			
		||||
	ann "github.com/containers/podman/v2/pkg/annotations"
 | 
			
		||||
	"github.com/containers/podman/v2/pkg/specgen"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@ package kube
 | 
			
		|||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"github.com/containers/buildah/pkg/parse"
 | 
			
		||||
	"github.com/containers/common/pkg/parse"
 | 
			
		||||
	"github.com/containers/podman/v2/libpod"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"github.com/sirupsen/logrus"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@ import (
 | 
			
		|||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/containers/buildah/pkg/parse"
 | 
			
		||||
	"github.com/containers/common/pkg/parse"
 | 
			
		||||
	spec "github.com/opencontainers/runtime-spec/specs-go"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"github.com/sirupsen/logrus"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,157 @@
 | 
			
		|||
package parse
 | 
			
		||||
 | 
			
		||||
// this package contains functions that parse and validate
 | 
			
		||||
// user input and is shared either amongst container engine subcommands
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ValidateVolumeOpts validates a volume's options
 | 
			
		||||
func ValidateVolumeOpts(options []string) ([]string, error) {
 | 
			
		||||
	var foundRootPropagation, foundRWRO, foundLabelChange, bindType, foundExec, foundDev, foundSuid int
 | 
			
		||||
	finalOpts := make([]string, 0, len(options))
 | 
			
		||||
	for _, opt := range options {
 | 
			
		||||
		switch opt {
 | 
			
		||||
		case "noexec", "exec":
 | 
			
		||||
			foundExec++
 | 
			
		||||
			if foundExec > 1 {
 | 
			
		||||
				return nil, errors.Errorf("invalid options %q, can only specify 1 'noexec' or 'exec' option", strings.Join(options, ", "))
 | 
			
		||||
			}
 | 
			
		||||
		case "nodev", "dev":
 | 
			
		||||
			foundDev++
 | 
			
		||||
			if foundDev > 1 {
 | 
			
		||||
				return nil, errors.Errorf("invalid options %q, can only specify 1 'nodev' or 'dev' option", strings.Join(options, ", "))
 | 
			
		||||
			}
 | 
			
		||||
		case "nosuid", "suid":
 | 
			
		||||
			foundSuid++
 | 
			
		||||
			if foundSuid > 1 {
 | 
			
		||||
				return nil, errors.Errorf("invalid options %q, can only specify 1 'nosuid' or 'suid' option", strings.Join(options, ", "))
 | 
			
		||||
			}
 | 
			
		||||
		case "rw", "ro":
 | 
			
		||||
			foundRWRO++
 | 
			
		||||
			if foundRWRO > 1 {
 | 
			
		||||
				return nil, errors.Errorf("invalid options %q, can only specify 1 'rw' or 'ro' option", strings.Join(options, ", "))
 | 
			
		||||
			}
 | 
			
		||||
		case "z", "Z", "O":
 | 
			
		||||
			foundLabelChange++
 | 
			
		||||
			if foundLabelChange > 1 {
 | 
			
		||||
				return nil, errors.Errorf("invalid options %q, can only specify 1 'z', 'Z', or 'O' option", strings.Join(options, ", "))
 | 
			
		||||
			}
 | 
			
		||||
		case "private", "rprivate", "shared", "rshared", "slave", "rslave", "unbindable", "runbindable":
 | 
			
		||||
			foundRootPropagation++
 | 
			
		||||
			if foundRootPropagation > 1 {
 | 
			
		||||
				return nil, errors.Errorf("invalid options %q, can only specify 1 '[r]shared', '[r]private', '[r]slave' or '[r]unbindable' option", strings.Join(options, ", "))
 | 
			
		||||
			}
 | 
			
		||||
		case "bind", "rbind":
 | 
			
		||||
			bindType++
 | 
			
		||||
			if bindType > 1 {
 | 
			
		||||
				return nil, errors.Errorf("invalid options %q, can only specify 1 '[r]bind' option", strings.Join(options, ", "))
 | 
			
		||||
			}
 | 
			
		||||
		case "cached", "delegated":
 | 
			
		||||
			// The discarded ops are OS X specific volume options
 | 
			
		||||
			// introduced in a recent Docker version.
 | 
			
		||||
			// They have no meaning on Linux, so here we silently
 | 
			
		||||
			// drop them. This matches Docker's behavior (the options
 | 
			
		||||
			// are intended to be always safe to use, even not on OS
 | 
			
		||||
			// X).
 | 
			
		||||
			continue
 | 
			
		||||
		default:
 | 
			
		||||
			return nil, errors.Errorf("invalid option type %q", opt)
 | 
			
		||||
		}
 | 
			
		||||
		finalOpts = append(finalOpts, opt)
 | 
			
		||||
	}
 | 
			
		||||
	return finalOpts, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Device parses device mapping string to a src, dest & permissions string
 | 
			
		||||
// Valid values for device looklike:
 | 
			
		||||
//    '/dev/sdc"
 | 
			
		||||
//    '/dev/sdc:/dev/xvdc"
 | 
			
		||||
//    '/dev/sdc:/dev/xvdc:rwm"
 | 
			
		||||
//    '/dev/sdc:rm"
 | 
			
		||||
func Device(device string) (src, dest, permissions string, err error) {
 | 
			
		||||
	permissions = "rwm"
 | 
			
		||||
	arr := strings.Split(device, ":")
 | 
			
		||||
	switch len(arr) {
 | 
			
		||||
	case 3:
 | 
			
		||||
		if !isValidDeviceMode(arr[2]) {
 | 
			
		||||
			return "", "", "", errors.Errorf("invalid device mode: %s", arr[2])
 | 
			
		||||
		}
 | 
			
		||||
		permissions = arr[2]
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case 2:
 | 
			
		||||
		if isValidDeviceMode(arr[1]) {
 | 
			
		||||
			permissions = arr[1]
 | 
			
		||||
		} else {
 | 
			
		||||
			if arr[1] == "" || arr[1][0] != '/' {
 | 
			
		||||
				return "", "", "", errors.Errorf("invalid device mode: %s", arr[1])
 | 
			
		||||
			}
 | 
			
		||||
			dest = arr[1]
 | 
			
		||||
		}
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case 1:
 | 
			
		||||
		if len(arr[0]) > 0 {
 | 
			
		||||
			src = arr[0]
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		fallthrough
 | 
			
		||||
	default:
 | 
			
		||||
		return "", "", "", errors.Errorf("invalid device specification: %s", device)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if dest == "" {
 | 
			
		||||
		dest = src
 | 
			
		||||
	}
 | 
			
		||||
	return src, dest, 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 {
 | 
			
		||||
	var legalDeviceMode = map[rune]bool{
 | 
			
		||||
		'r': true,
 | 
			
		||||
		'w': true,
 | 
			
		||||
		'm': true,
 | 
			
		||||
	}
 | 
			
		||||
	if mode == "" {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	for _, c := range mode {
 | 
			
		||||
		if !legalDeviceMode[c] {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		legalDeviceMode[c] = false
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ValidateVolumeHostDir validates a volume mount's source directory
 | 
			
		||||
func ValidateVolumeHostDir(hostDir string) error {
 | 
			
		||||
	if hostDir == "" {
 | 
			
		||||
		return errors.Errorf("host directory cannot be empty")
 | 
			
		||||
	}
 | 
			
		||||
	if filepath.IsAbs(hostDir) {
 | 
			
		||||
		if _, err := os.Stat(hostDir); err != nil {
 | 
			
		||||
			return errors.Wrapf(err, "error checking path %q", hostDir)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// If hostDir is not an absolute path, that means the user wants to create a
 | 
			
		||||
	// named volume. This will be done later on in the code.
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ValidateVolumeCtrDir validates a volume mount's destination directory.
 | 
			
		||||
func ValidateVolumeCtrDir(ctrDir string) error {
 | 
			
		||||
	if ctrDir == "" {
 | 
			
		||||
		return errors.Errorf("container directory cannot be empty")
 | 
			
		||||
	}
 | 
			
		||||
	if !filepath.IsAbs(ctrDir) {
 | 
			
		||||
		return errors.Errorf("invalid container path %q, must be an absolute path", ctrDir)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,51 @@
 | 
			
		|||
// +build linux darwin
 | 
			
		||||
 | 
			
		||||
package parse
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
 | 
			
		||||
	"github.com/containers/storage/pkg/unshare"
 | 
			
		||||
	"github.com/opencontainers/runc/libcontainer/configs"
 | 
			
		||||
	"github.com/opencontainers/runc/libcontainer/devices"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func DeviceFromPath(device string) ([]configs.Device, error) {
 | 
			
		||||
	var devs []configs.Device
 | 
			
		||||
	src, dst, permissions, err := Device(device)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if unshare.IsRootless() && src != dst {
 | 
			
		||||
		return nil, errors.Errorf("Renaming device %s to %s is not supported in rootless containers", src, dst)
 | 
			
		||||
	}
 | 
			
		||||
	srcInfo, err := os.Stat(src)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(err, "error getting info of source device %s", src)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !srcInfo.IsDir() {
 | 
			
		||||
 | 
			
		||||
		dev, err := devices.DeviceFromPath(src, permissions)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, errors.Wrapf(err, "%s is not a valid device", src)
 | 
			
		||||
		}
 | 
			
		||||
		dev.Path = dst
 | 
			
		||||
		devs = append(devs, *dev)
 | 
			
		||||
		return devs, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If source device is a directory
 | 
			
		||||
	srcDevices, err := devices.GetDevices(src)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(err, "error getting source devices from directory %s", src)
 | 
			
		||||
	}
 | 
			
		||||
	for _, d := range srcDevices {
 | 
			
		||||
		d.Path = filepath.Join(dst, filepath.Base(d.Path))
 | 
			
		||||
		d.Permissions = configs.DevicePermissions(permissions)
 | 
			
		||||
		devs = append(devs, *d)
 | 
			
		||||
	}
 | 
			
		||||
	return devs, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -97,6 +97,7 @@ github.com/containers/common/pkg/capabilities
 | 
			
		|||
github.com/containers/common/pkg/cgroupv2
 | 
			
		||||
github.com/containers/common/pkg/completion
 | 
			
		||||
github.com/containers/common/pkg/config
 | 
			
		||||
github.com/containers/common/pkg/parse
 | 
			
		||||
github.com/containers/common/pkg/report
 | 
			
		||||
github.com/containers/common/pkg/report/camelcase
 | 
			
		||||
github.com/containers/common/pkg/retry
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue