mirror of
https://github.com/containers/buildah.git
synced 2026-02-05 09:45:38 +01:00
Add support for containers.conf
This is a rework of Qi Wang's patches. Import package pkg/config from containers/common to read containers.conf This patch allows users to specify default values stored in containers.conf that will modify the behaviour of buildah tool. Signed-off-by: Qi Wang <qiwan@redhat.com> Signed-off-by: Daniel J Walsh <dwalsh@redhat.com> Closes: #2011 Approved by: TomSweeneyRedHat
This commit is contained in:
committed by
Atomic Bot
parent
bf14e6ca2d
commit
09d1c24e3d
31
buildah.go
31
buildah.go
@@ -8,10 +8,10 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/containers/buildah/docker"
|
||||
"github.com/containers/buildah/util"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage"
|
||||
"github.com/containers/storage/pkg/ioutils"
|
||||
@@ -180,13 +180,8 @@ type Builder struct {
|
||||
CNIConfigDir string
|
||||
// ID mapping options to use when running processes in the container with non-host user namespaces.
|
||||
IDMappingOptions IDMappingOptions
|
||||
// AddCapabilities is a list of capabilities to add to the default set when running
|
||||
// commands in the container.
|
||||
AddCapabilities []string
|
||||
// DropCapabilities is a list of capabilities to remove from the default set,
|
||||
// after processing the AddCapabilities set, when running commands in the container.
|
||||
// If a capability appears in both lists, it will be dropped.
|
||||
DropCapabilities []string
|
||||
// Capabilities is a list of capabilities to use when running commands in the container.
|
||||
Capabilities []string
|
||||
// PrependedEmptyLayers are history entries that we'll add to a
|
||||
// committed image, after any history items that we inherit from a base
|
||||
// image, but before the history item for the layer that we're
|
||||
@@ -229,13 +224,11 @@ type BuilderInfo struct {
|
||||
DefaultMountsFilePath string
|
||||
Isolation string
|
||||
NamespaceOptions NamespaceOptions
|
||||
Capabilities []string
|
||||
ConfigureNetwork string
|
||||
CNIPluginPath string
|
||||
CNIConfigDir string
|
||||
IDMappingOptions IDMappingOptions
|
||||
DefaultCapabilities []string
|
||||
AddCapabilities []string
|
||||
DropCapabilities []string
|
||||
History []v1.History
|
||||
Devices []configs.Device
|
||||
}
|
||||
@@ -255,6 +248,7 @@ func GetBuildInfo(b *Builder) BuilderInfo {
|
||||
EmptyLayer: false,
|
||||
})
|
||||
history = append(history, copyHistory(b.AppendedEmptyLayers)...)
|
||||
sort.Strings(b.Capabilities)
|
||||
return BuilderInfo{
|
||||
Type: b.Type,
|
||||
FromImage: b.FromImage,
|
||||
@@ -278,9 +272,7 @@ func GetBuildInfo(b *Builder) BuilderInfo {
|
||||
CNIPluginPath: b.CNIPluginPath,
|
||||
CNIConfigDir: b.CNIConfigDir,
|
||||
IDMappingOptions: b.IDMappingOptions,
|
||||
DefaultCapabilities: append([]string{}, util.DefaultCapabilities...),
|
||||
AddCapabilities: append([]string{}, b.AddCapabilities...),
|
||||
DropCapabilities: append([]string{}, b.DropCapabilities...),
|
||||
Capabilities: b.Capabilities,
|
||||
History: history,
|
||||
Devices: b.Devices,
|
||||
}
|
||||
@@ -406,19 +398,16 @@ type BuilderOptions struct {
|
||||
CNIConfigDir string
|
||||
// ID mapping options to use if we're setting up our own user namespace.
|
||||
IDMappingOptions *IDMappingOptions
|
||||
// AddCapabilities is a list of capabilities to add to the default set when
|
||||
// Capabilities is a list of capabilities to use when
|
||||
// running commands in the container.
|
||||
AddCapabilities []string
|
||||
// DropCapabilities is a list of capabilities to remove from the default set,
|
||||
// after processing the AddCapabilities set, when running commands in the
|
||||
// container. If a capability appears in both lists, it will be dropped.
|
||||
DropCapabilities []string
|
||||
|
||||
Capabilities []string
|
||||
CommonBuildOpts *CommonBuildOptions
|
||||
// Format for the container image
|
||||
Format string
|
||||
// Devices are the additional devices to add to the containers
|
||||
Devices []configs.Device
|
||||
//DefaultEnv for containers
|
||||
DefaultEnv []string
|
||||
}
|
||||
|
||||
// ImportOptions are used to initialize a Builder from an existing container
|
||||
|
||||
@@ -69,7 +69,7 @@ func init() {
|
||||
budFlags.StringVar(&budFlagResults.Runtime, "runtime", util.Runtime(), "`path` to an alternate runtime. Use BUILDAH_RUNTIME environment variable to override.")
|
||||
|
||||
layerFlags := buildahcli.GetLayerFlags(&layerFlagsResults)
|
||||
fromAndBudFlags := buildahcli.GetFromAndBudFlags(&fromAndBudResults, &userNSResults, &namespaceResults)
|
||||
fromAndBudFlags := buildahcli.GetFromAndBudFlags(&fromAndBudResults, &userNSResults, &namespaceResults, defaultContainerConfig)
|
||||
|
||||
flags.AddFlagSet(&budFlags)
|
||||
flags.AddFlagSet(&layerFlags)
|
||||
@@ -224,7 +224,7 @@ func budCmd(c *cobra.Command, inputArgs []string, iopts budResults) error {
|
||||
runtimeFlags = append(runtimeFlags, "--"+arg)
|
||||
}
|
||||
|
||||
commonOpts, err := parse.CommonBuildOptions(c)
|
||||
commonOpts, err := parse.CommonBuildOptions(c, defaultContainerConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -281,7 +281,7 @@ func budCmd(c *cobra.Command, inputArgs []string, iopts budResults) error {
|
||||
|
||||
defaultsMountFile, _ := c.PersistentFlags().GetString("defaults-mount-file")
|
||||
transientMounts := []imagebuildah.Mount{}
|
||||
for _, volume := range iopts.Volumes {
|
||||
for _, volume := range append(defaultContainerConfig.Containers.AdditionalVolumes, iopts.Volumes...) {
|
||||
mount, err := parse.Volume(volume)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -291,7 +291,7 @@ func budCmd(c *cobra.Command, inputArgs []string, iopts budResults) error {
|
||||
}
|
||||
|
||||
devices := []configs.Device{}
|
||||
for _, device := range iopts.Devices {
|
||||
for _, device := range append(defaultContainerConfig.Containers.AdditionalDevices, iopts.Devices...) {
|
||||
dev, err := parse.DeviceFromPath(device)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -299,6 +299,8 @@ func budCmd(c *cobra.Command, inputArgs []string, iopts budResults) error {
|
||||
devices = append(devices, dev...)
|
||||
}
|
||||
|
||||
capabilities := defaultContainerConfig.Capabilities("", iopts.CapAdd, iopts.CapDrop)
|
||||
|
||||
options := imagebuildah.BuildOptions{
|
||||
ContextDirectory: contextDir,
|
||||
PullPolicy: pullPolicy,
|
||||
@@ -322,8 +324,7 @@ func budCmd(c *cobra.Command, inputArgs []string, iopts budResults) error {
|
||||
CNIPluginPath: iopts.CNIPlugInPath,
|
||||
CNIConfigDir: iopts.CNIConfigDir,
|
||||
IDMappingOptions: idmappingOptions,
|
||||
AddCapabilities: iopts.CapAdd,
|
||||
DropCapabilities: iopts.CapDrop,
|
||||
Capabilities: capabilities,
|
||||
CommonBuildOpts: commonOpts,
|
||||
DefaultMountsFilePath: defaultsMountFile,
|
||||
IIDFile: iopts.Iidfile,
|
||||
@@ -338,6 +339,7 @@ func budCmd(c *cobra.Command, inputArgs []string, iopts budResults) error {
|
||||
Target: iopts.Target,
|
||||
TransientMounts: transientMounts,
|
||||
Devices: devices,
|
||||
DefaultEnv: defaultContainerConfig.GetDefaultEnv(),
|
||||
}
|
||||
|
||||
if iopts.Quiet {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/containers/buildah"
|
||||
"github.com/containers/buildah/pkg/umask"
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/common/pkg/unshare"
|
||||
"github.com/containers/image/v5/image"
|
||||
is "github.com/containers/image/v5/storage"
|
||||
@@ -20,7 +21,12 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var needToShutdownStore = false
|
||||
var (
|
||||
// defaultContainerConfig structure defines the default container
|
||||
// configuration, including customizations made in containers.conf
|
||||
defaultContainerConfig = getDefaultConfig()
|
||||
needToShutdownStore = false
|
||||
)
|
||||
|
||||
func getStore(c *cobra.Command) (storage.Store, error) {
|
||||
options, err := storage.DefaultStoreOptions(unshare.IsRootless(), unshare.GetRootlessUID())
|
||||
@@ -424,3 +430,13 @@ Flags:
|
||||
{{end}}
|
||||
`
|
||||
}
|
||||
|
||||
func getDefaultConfig() *config.Config {
|
||||
var err error
|
||||
conf, err := config.NewConfig("")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error loading container config %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return conf
|
||||
}
|
||||
|
||||
@@ -176,33 +176,32 @@ func updateConfig(builder *buildah.Builder, c *cobra.Command, iopts configResult
|
||||
}
|
||||
conditionallyAddHistory(builder, c, "/bin/sh -c #(nop) EXPOSE %s", strings.Join(iopts.ports, " "))
|
||||
}
|
||||
if c.Flag("env").Changed {
|
||||
for _, envSpec := range iopts.env {
|
||||
env := strings.SplitN(envSpec, "=", 2)
|
||||
if len(env) > 1 {
|
||||
var unexpanded []string
|
||||
getenv := func(name string) string {
|
||||
for _, envvar := range builder.Env() {
|
||||
val := strings.SplitN(envvar, "=", 2)
|
||||
if len(val) == 2 && val[0] == name {
|
||||
return val[1]
|
||||
}
|
||||
|
||||
for _, envSpec := range iopts.env {
|
||||
env := strings.SplitN(envSpec, "=", 2)
|
||||
if len(env) > 1 {
|
||||
var unexpanded []string
|
||||
getenv := func(name string) string {
|
||||
for _, envvar := range builder.Env() {
|
||||
val := strings.SplitN(envvar, "=", 2)
|
||||
if len(val) == 2 && val[0] == name {
|
||||
return val[1]
|
||||
}
|
||||
logrus.Errorf("error expanding variable %q: no value set in configuration", name)
|
||||
unexpanded = append(unexpanded, name)
|
||||
return name
|
||||
}
|
||||
env[1] = os.Expand(env[1], getenv)
|
||||
builder.SetEnv(env[0], env[1])
|
||||
} else if strings.HasSuffix(env[0], "-") {
|
||||
env[0] = strings.TrimSuffix(env[0], "-")
|
||||
builder.UnsetEnv(env[0])
|
||||
} else {
|
||||
logrus.Errorf("error setting variable %q: no value given.", env[0])
|
||||
logrus.Errorf("error expanding variable %q: no value set in configuration", name)
|
||||
unexpanded = append(unexpanded, name)
|
||||
return name
|
||||
}
|
||||
env[1] = os.Expand(env[1], getenv)
|
||||
builder.SetEnv(env[0], env[1])
|
||||
} else if strings.HasSuffix(env[0], "-") {
|
||||
env[0] = strings.TrimSuffix(env[0], "-")
|
||||
builder.UnsetEnv(env[0])
|
||||
} else {
|
||||
logrus.Errorf("error setting variable %q: no value given.", env[0])
|
||||
}
|
||||
conditionallyAddHistory(builder, c, "/bin/sh -c #(nop) ENV %s", strings.Join(iopts.env, " "))
|
||||
}
|
||||
conditionallyAddHistory(builder, c, "/bin/sh -c #(nop) ENV %s", strings.Join(iopts.env, " "))
|
||||
if c.Flag("entrypoint").Changed {
|
||||
updateEntrypoint(builder, iopts)
|
||||
conditionallyAddHistory(builder, c, "/bin/sh -c #(nop) ENTRYPOINT %s", iopts.entrypoint)
|
||||
|
||||
@@ -78,7 +78,7 @@ func init() {
|
||||
flags.BoolVar(&opts.tlsVerify, "tls-verify", true, "require HTTPS and verify certificates when accessing the registry")
|
||||
|
||||
// Add in the common flags
|
||||
fromAndBudFlags := buildahcli.GetFromAndBudFlags(&fromAndBudResults, &userNSResults, &namespaceResults)
|
||||
fromAndBudFlags := buildahcli.GetFromAndBudFlags(&fromAndBudResults, &userNSResults, &namespaceResults, defaultContainerConfig)
|
||||
flags.AddFlagSet(&fromAndBudFlags)
|
||||
|
||||
rootCmd.AddCommand(fromCommand)
|
||||
@@ -179,7 +179,6 @@ func fromCmd(c *cobra.Command, args []string, iopts fromReply) error {
|
||||
if err := buildahcli.CheckAuthFile(iopts.authfile); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
systemContext, err := parse.SystemContextFromOptions(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error building system context")
|
||||
@@ -218,7 +217,7 @@ func fromCmd(c *cobra.Command, args []string, iopts fromReply) error {
|
||||
return err
|
||||
}
|
||||
|
||||
commonOpts, err := parse.CommonBuildOptions(c)
|
||||
commonOpts, err := parse.CommonBuildOptions(c, defaultContainerConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -244,7 +243,7 @@ func fromCmd(c *cobra.Command, args []string, iopts fromReply) error {
|
||||
}
|
||||
|
||||
devices := []configs.Device{}
|
||||
for _, device := range iopts.Devices {
|
||||
for _, device := range append(defaultContainerConfig.Containers.AdditionalDevices, iopts.Devices...) {
|
||||
dev, err := parse.DeviceFromPath(device)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -252,6 +251,7 @@ func fromCmd(c *cobra.Command, args []string, iopts fromReply) error {
|
||||
devices = append(devices, dev...)
|
||||
}
|
||||
|
||||
capabilities := defaultContainerConfig.Capabilities("", iopts.CapAdd, iopts.CapDrop)
|
||||
options := buildah.BuilderOptions{
|
||||
FromImage: args[0],
|
||||
Container: iopts.name,
|
||||
@@ -265,12 +265,12 @@ func fromCmd(c *cobra.Command, args []string, iopts fromReply) error {
|
||||
CNIPluginPath: iopts.CNIPlugInPath,
|
||||
CNIConfigDir: iopts.CNIConfigDir,
|
||||
IDMappingOptions: idmappingOptions,
|
||||
AddCapabilities: iopts.CapAdd,
|
||||
DropCapabilities: iopts.CapDrop,
|
||||
Capabilities: capabilities,
|
||||
CommonBuildOpts: commonOpts,
|
||||
Format: format,
|
||||
BlobDirectory: iopts.BlobCache,
|
||||
Devices: devices,
|
||||
DefaultEnv: defaultContainerConfig.GetDefaultEnv(),
|
||||
}
|
||||
|
||||
if !iopts.quiet {
|
||||
|
||||
@@ -126,6 +126,7 @@ func runCmd(c *cobra.Command, args []string, iopts runInputOptions) error {
|
||||
}
|
||||
|
||||
options := buildah.RunOptions{
|
||||
Env: defaultContainerConfig.Containers.Env,
|
||||
Hostname: iopts.hostname,
|
||||
Runtime: iopts.runtime,
|
||||
Args: runtimeFlags,
|
||||
|
||||
3
go.mod
3
go.mod
@@ -5,11 +5,12 @@ go 1.12
|
||||
require (
|
||||
github.com/blang/semver v3.5.0+incompatible // indirect
|
||||
github.com/containernetworking/cni v0.7.1
|
||||
github.com/containers/common v0.0.7
|
||||
github.com/containers/common v0.0.8-0.20200108114752-d87ce6ce296b
|
||||
github.com/containers/image/v5 v5.1.0
|
||||
github.com/containers/storage v1.15.5
|
||||
github.com/cyphar/filepath-securejoin v0.2.2
|
||||
github.com/docker/distribution v2.7.1+incompatible
|
||||
github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
github.com/docker/go-units v0.4.0
|
||||
github.com/docker/libnetwork v0.8.0-dev.2.0.20190625141545-5a177b73e316
|
||||
|
||||
4
go.sum
4
go.sum
@@ -62,6 +62,10 @@ github.com/containers/common v0.0.5 h1:Hi4+eyUZx8hXB4reLNPbdT6XT8MGMAzdlbg8V+Wif
|
||||
github.com/containers/common v0.0.5/go.mod h1:lhWV3MLhO1+KGE2x6v9+K38MxpjXGso+edmpkFnCOqI=
|
||||
github.com/containers/common v0.0.7 h1:eKYZLKfJ2d/RNDgecLDFv45cHb4imYzIcrQHx1Y029M=
|
||||
github.com/containers/common v0.0.7/go.mod h1:lhWV3MLhO1+KGE2x6v9+K38MxpjXGso+edmpkFnCOqI=
|
||||
github.com/containers/common v0.0.8-0.20200106141003-a79791495fd1 h1:udiDqxQSdunVXNjBW4icHrnFLNOiTpvH6GRG+ywA4f4=
|
||||
github.com/containers/common v0.0.8-0.20200106141003-a79791495fd1/go.mod h1:lhWV3MLhO1+KGE2x6v9+K38MxpjXGso+edmpkFnCOqI=
|
||||
github.com/containers/common v0.0.8-0.20200108114752-d87ce6ce296b h1:G+DKyzrku0fC5Qa3paArNBERTwRleTg45ypY0qjo7YM=
|
||||
github.com/containers/common v0.0.8-0.20200108114752-d87ce6ce296b/go.mod h1:ss8uGpUsaDE4DPmaVFOjzKrlgf5eUnSAWL+d/PYGaoM=
|
||||
github.com/containers/image/v4 v4.0.1 h1:idNGHChj0Pyv3vLrxul2oSVMZLeFqpoq3CjLeVgapSQ=
|
||||
github.com/containers/image/v4 v4.0.1/go.mod h1:0ASJH1YgJiX/eqFZObqepgsvIA4XjCgpyfwn9pDGafA=
|
||||
github.com/containers/image/v5 v5.0.0 h1:arnXgbt1ucsC/ndtSpiQY87rA0UjhF+/xQnPzqdBDn4=
|
||||
|
||||
@@ -122,14 +122,10 @@ type BuildOptions struct {
|
||||
// ID mapping options to use if we're setting up our own user namespace
|
||||
// when handling RUN instructions.
|
||||
IDMappingOptions *buildah.IDMappingOptions
|
||||
// AddCapabilities is a list of capabilities to add to the default set when
|
||||
// Capabilities is a list of capabilities to use when
|
||||
// handling RUN instructions.
|
||||
AddCapabilities []string
|
||||
// DropCapabilities is a list of capabilities to remove from the default set
|
||||
// when handling RUN instructions. If a capability appears in both lists, it
|
||||
// will be dropped.
|
||||
DropCapabilities []string
|
||||
CommonBuildOpts *buildah.CommonBuildOptions
|
||||
Capabilities []string
|
||||
CommonBuildOpts *buildah.CommonBuildOptions
|
||||
// DefaultMountsFilePath is the file path holding the mounts to be mounted in "host-path:container-path" format
|
||||
DefaultMountsFilePath string
|
||||
// IIDFile tells the builder to write the image ID to the specified file
|
||||
@@ -160,6 +156,8 @@ type BuildOptions struct {
|
||||
Target string
|
||||
// Devices are the additional devices to add to the containers
|
||||
Devices []configs.Device
|
||||
//DefaultEnv for containers
|
||||
DefaultEnv []string
|
||||
}
|
||||
|
||||
// BuildDockerfiles parses a set of one or more Dockerfiles (which may be
|
||||
@@ -250,6 +248,7 @@ func BuildDockerfiles(ctx context.Context, store storage.Store, options BuildOpt
|
||||
return "", nil, errors.Wrapf(err, "error creating build executor")
|
||||
}
|
||||
b := imagebuilder.NewBuilder(options.Args)
|
||||
b.Env = append(options.DefaultEnv, b.Env...)
|
||||
stages, err := imagebuilder.NewStages(mainNode, b)
|
||||
if err != nil {
|
||||
return "", nil, errors.Wrap(err, "error reading multiple stages")
|
||||
|
||||
@@ -91,8 +91,7 @@ type Executor struct {
|
||||
excludes []string
|
||||
unusedArgs map[string]struct{}
|
||||
buildArgs map[string]string
|
||||
addCapabilities []string
|
||||
dropCapabilities []string
|
||||
capabilities []string
|
||||
devices []configs.Device
|
||||
}
|
||||
|
||||
@@ -148,8 +147,7 @@ func NewExecutor(store storage.Store, options BuildOptions, mainNode *parser.Nod
|
||||
blobDirectory: options.BlobDirectory,
|
||||
unusedArgs: make(map[string]struct{}),
|
||||
buildArgs: options.Args,
|
||||
addCapabilities: options.AddCapabilities,
|
||||
dropCapabilities: options.DropCapabilities,
|
||||
capabilities: options.Capabilities,
|
||||
devices: options.Devices,
|
||||
}
|
||||
if exec.err == nil {
|
||||
|
||||
@@ -605,8 +605,7 @@ func (s *StageExecutor) prepare(ctx context.Context, stage imagebuilder.Stage, f
|
||||
CommonBuildOpts: s.executor.commonBuildOptions,
|
||||
DefaultMountsFilePath: s.executor.defaultMountsFilePath,
|
||||
Format: s.executor.outputFormat,
|
||||
AddCapabilities: s.executor.addCapabilities,
|
||||
DropCapabilities: s.executor.dropCapabilities,
|
||||
Capabilities: s.executor.capabilities,
|
||||
Devices: s.executor.devices,
|
||||
}
|
||||
|
||||
|
||||
15
new.go
15
new.go
@@ -398,14 +398,13 @@ func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions
|
||||
UIDMap: uidmap,
|
||||
GIDMap: gidmap,
|
||||
},
|
||||
AddCapabilities: copyStringSlice(options.AddCapabilities),
|
||||
DropCapabilities: copyStringSlice(options.DropCapabilities),
|
||||
CommonBuildOpts: options.CommonBuildOpts,
|
||||
TopLayer: topLayer,
|
||||
Args: options.Args,
|
||||
Format: options.Format,
|
||||
TempVolumes: map[string]bool{},
|
||||
Devices: options.Devices,
|
||||
Capabilities: copyStringSlice(options.Capabilities),
|
||||
CommonBuildOpts: options.CommonBuildOpts,
|
||||
TopLayer: topLayer,
|
||||
Args: options.Args,
|
||||
Format: options.Format,
|
||||
TempVolumes: map[string]bool{},
|
||||
Devices: options.Devices,
|
||||
}
|
||||
|
||||
if options.Mount {
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/containers/buildah"
|
||||
"github.com/containers/buildah/util"
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
@@ -175,7 +176,7 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet {
|
||||
return fs
|
||||
}
|
||||
|
||||
func GetFromAndBudFlags(flags *FromAndBudResults, usernsResults *UserNSResults, namespaceResults *NameSpaceResults) pflag.FlagSet {
|
||||
func GetFromAndBudFlags(flags *FromAndBudResults, usernsResults *UserNSResults, namespaceResults *NameSpaceResults, defaultConfig *config.Config) pflag.FlagSet {
|
||||
fs := pflag.FlagSet{}
|
||||
fs.StringSliceVar(&flags.AddHost, "add-host", []string{}, "add a custom host-to-IP mapping (`host:ip`) (default [])")
|
||||
fs.StringVar(&flags.BlobCache, "blob-cache", "", "assume image blobs in the specified directory will be available for pushing")
|
||||
@@ -190,10 +191,10 @@ func GetFromAndBudFlags(flags *FromAndBudResults, usernsResults *UserNSResults,
|
||||
fs.Uint64VarP(&flags.CPUShares, "cpu-shares", "c", 0, "CPU shares (relative weight)")
|
||||
fs.StringVar(&flags.CPUSetCPUs, "cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)")
|
||||
fs.StringVar(&flags.CPUSetMems, "cpuset-mems", "", "memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.")
|
||||
fs.StringArrayVar(&flags.Devices, "device", []string{}, "Additional devices to be used within containers (default [])")
|
||||
fs.StringSliceVar(&flags.DNSSearch, "dns-search", []string{}, "Set custom DNS search domains")
|
||||
fs.StringSliceVar(&flags.DNSServers, "dns", []string{}, "Set custom DNS servers or disable it completely by setting it to 'none', which prevents the automatic creation of `/etc/resolv.conf`.")
|
||||
fs.StringSliceVar(&flags.DNSOptions, "dns-option", []string{}, "Set custom DNS options")
|
||||
fs.StringArrayVar(&flags.Devices, "device", defaultConfig.Containers.AdditionalDevices, "Additional devices to be used within containers (default [])")
|
||||
fs.StringSliceVar(&flags.DNSSearch, "dns-search", defaultConfig.Containers.DNSSearches, "Set custom DNS search domains")
|
||||
fs.StringSliceVar(&flags.DNSServers, "dns", defaultConfig.Containers.DNSServers, "Set custom DNS servers or disable it completely by setting it to 'none', which prevents the automatic creation of `/etc/resolv.conf`.")
|
||||
fs.StringSliceVar(&flags.DNSOptions, "dns-option", defaultConfig.Containers.DNSOptions, "Set custom DNS options")
|
||||
fs.BoolVar(&flags.HTTPProxy, "http-proxy", true, "pass through HTTP Proxy environment variables")
|
||||
fs.StringVar(&flags.Isolation, "isolation", DefaultIsolation(), "`type` of process isolation to use. Use BUILDAH_ISOLATION environment variable to override.")
|
||||
fs.StringVarP(&flags.Memory, "memory", "m", "", "memory limit (format: <number>[<unit>], where unit = b, k, m or g)")
|
||||
@@ -207,9 +208,9 @@ func GetFromAndBudFlags(flags *FromAndBudResults, usernsResults *UserNSResults,
|
||||
panic(fmt.Sprintf("error marking override-arch as hidden: %v", err))
|
||||
}
|
||||
fs.StringArrayVar(&flags.SecurityOpt, "security-opt", []string{}, "security options (default [])")
|
||||
fs.StringVar(&flags.ShmSize, "shm-size", "65536k", "size of '/dev/shm'. The format is `<number><unit>`.")
|
||||
fs.StringSliceVar(&flags.Ulimit, "ulimit", []string{}, "ulimit options (default [])")
|
||||
fs.StringArrayVarP(&flags.Volumes, "volume", "v", []string{}, "bind mount a volume into the container (default [])")
|
||||
fs.StringVar(&flags.ShmSize, "shm-size", defaultConfig.Containers.ShmSize, "size of '/dev/shm'. The format is `<number><unit>`.")
|
||||
fs.StringSliceVar(&flags.Ulimit, "ulimit", defaultConfig.Containers.DefaultUlimits, "ulimit options")
|
||||
fs.StringArrayVarP(&flags.Volumes, "volume", "v", defaultConfig.Containers.AdditionalVolumes, "bind mount a volume into the container")
|
||||
|
||||
// Add in the usernamespace and namespaceflags
|
||||
usernsFlags := GetUserNSFlags(usernsResults)
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"unicode"
|
||||
|
||||
"github.com/containers/buildah"
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
units "github.com/docker/go-units"
|
||||
@@ -43,7 +44,7 @@ var (
|
||||
)
|
||||
|
||||
// CommonBuildOptions parses the build options from the bud cli
|
||||
func CommonBuildOptions(c *cobra.Command) (*buildah.CommonBuildOptions, error) {
|
||||
func CommonBuildOptions(c *cobra.Command, defaultConfig *config.Config) (*buildah.CommonBuildOptions, error) {
|
||||
var (
|
||||
memoryLimit int64
|
||||
memorySwap int64
|
||||
@@ -80,6 +81,7 @@ func CommonBuildOptions(c *cobra.Command) (*buildah.CommonBuildOptions, error) {
|
||||
|
||||
noDNS = false
|
||||
dnsServers, _ := c.Flags().GetStringSlice("dns")
|
||||
dnsServers = append(defaultConfig.Containers.DNSServers, dnsServers...)
|
||||
for _, server := range dnsServers {
|
||||
if strings.ToLower(server) == "none" {
|
||||
noDNS = true
|
||||
@@ -90,11 +92,13 @@ func CommonBuildOptions(c *cobra.Command) (*buildah.CommonBuildOptions, error) {
|
||||
}
|
||||
|
||||
dnsSearch, _ := c.Flags().GetStringSlice("dns-search")
|
||||
dnsSearch = append(defaultConfig.Containers.DNSSearches, dnsSearch...)
|
||||
if noDNS && len(dnsSearch) > 0 {
|
||||
return nil, errors.Errorf("invalid --dns-search, --dns-search may not be used with --dns=none")
|
||||
}
|
||||
|
||||
dnsOptions, _ := c.Flags().GetStringSlice("dns-option")
|
||||
dnsOptions = append(defaultConfig.Containers.DNSOptions, dnsOptions...)
|
||||
if noDNS && len(dnsOptions) > 0 {
|
||||
return nil, errors.Errorf("invalid --dns-option, --dns-option may not be used with --dns=none")
|
||||
}
|
||||
@@ -111,6 +115,8 @@ func CommonBuildOptions(c *cobra.Command) (*buildah.CommonBuildOptions, error) {
|
||||
cpuShares, _ := c.Flags().GetUint64("cpu-shares")
|
||||
httpProxy, _ := c.Flags().GetBool("http-proxy")
|
||||
ulimit, _ := c.Flags().GetStringSlice("ulimit")
|
||||
ulimit = append(defaultConfig.Containers.DefaultUlimits, ulimit...)
|
||||
|
||||
commonOpts := &buildah.CommonBuildOptions{
|
||||
AddHost: addHost,
|
||||
CgroupParent: c.Flag("cgroup-parent").Value.String(),
|
||||
|
||||
30
run_linux.go
30
run_linux.go
@@ -31,6 +31,7 @@ import (
|
||||
"github.com/containers/storage/pkg/ioutils"
|
||||
"github.com/containers/storage/pkg/reexec"
|
||||
"github.com/containers/storage/pkg/stringid"
|
||||
"github.com/docker/docker/oci/caps"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/docker/libnetwork/resolvconf"
|
||||
"github.com/docker/libnetwork/types"
|
||||
@@ -1799,21 +1800,27 @@ func setupCapDrop(g *generate.Generator, caps ...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupCapabilities(g *generate.Generator, firstAdds, firstDrops, secondAdds, secondDrops []string) error {
|
||||
func setupCapabilities(g *generate.Generator, defaultCapabilities, adds, drops []string) error {
|
||||
g.ClearProcessCapabilities()
|
||||
if err := setupCapAdd(g, util.DefaultCapabilities...); err != nil {
|
||||
if err := setupCapAdd(g, defaultCapabilities...); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := setupCapAdd(g, firstAdds...); err != nil {
|
||||
for _, c := range adds {
|
||||
if strings.ToLower(c) == "all" {
|
||||
adds = caps.GetAllCapabilities()
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, c := range drops {
|
||||
if strings.ToLower(c) == "all" {
|
||||
g.ClearProcessCapabilities()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if err := setupCapAdd(g, adds...); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := setupCapDrop(g, firstDrops...); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := setupCapAdd(g, secondAdds...); err != nil {
|
||||
return err
|
||||
}
|
||||
return setupCapDrop(g, secondDrops...)
|
||||
return setupCapDrop(g, drops...)
|
||||
}
|
||||
|
||||
// Search for a command that isn't given as an absolute path using the $PATH
|
||||
@@ -1880,7 +1887,7 @@ func (b *Builder) configureUIDGID(g *generate.Generator, mountPoint string, opti
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := setupCapabilities(g, b.AddCapabilities, b.DropCapabilities, options.AddCapabilities, options.DropCapabilities); err != nil {
|
||||
if err := setupCapabilities(g, b.Capabilities, options.AddCapabilities, options.DropCapabilities); err != nil {
|
||||
return "", err
|
||||
}
|
||||
g.SetProcessUID(user.UID)
|
||||
@@ -1901,6 +1908,7 @@ func (b *Builder) configureUIDGID(g *generate.Generator, mountPoint string, opti
|
||||
|
||||
func (b *Builder) configureEnvironment(g *generate.Generator, options RunOptions) {
|
||||
g.ClearProcessEnv()
|
||||
|
||||
if b.CommonBuildOpts.HTTPProxy {
|
||||
for _, envSpec := range []string{
|
||||
"http_proxy",
|
||||
|
||||
60
tests/containers.conf
Normal file
60
tests/containers.conf
Normal file
@@ -0,0 +1,60 @@
|
||||
[containers]
|
||||
|
||||
# A list of ulimits to be set in containers by default, specified as
|
||||
# "<ulimit name>=<soft limit>:<hard limit>", for example:
|
||||
# "nofile=1024:2048"
|
||||
# See setrlimit(2) for a list of resource names.
|
||||
# Any limit not specified here will be inherited from the process launching the
|
||||
# container engine.
|
||||
# Ulimits has limits for non privileged container engines.
|
||||
#
|
||||
default_ulimits = [
|
||||
"nofile=500:500",
|
||||
]
|
||||
|
||||
# Environment variable list for the conmon process; used for passing necessary
|
||||
# environment variables to conmon or the runtime.
|
||||
#
|
||||
env = [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"foo=bar",
|
||||
]
|
||||
|
||||
# container engines use container separation using MAC(SELinux) labeling.
|
||||
# Flag is ignored on label disabled systems.
|
||||
#
|
||||
label = true
|
||||
|
||||
# Size of /dev/shm. Specified as <number><unit>.
|
||||
# Unit is optional, values:
|
||||
# b (bytes), k (kilobytes), m (megabytes), or g (gigabytes).
|
||||
# If the unit is omitted, the system uses bytes.
|
||||
#
|
||||
shm_size = "200k"
|
||||
|
||||
# List of additional devices. Specified as
|
||||
# "<device-on-host>:<device-on-container>:<permissions>", for example:
|
||||
# "/dev/sdc:/dev/xvdc:rwm".
|
||||
# If it is empty or commented out, only the default devices will be used
|
||||
#
|
||||
additional_devices = [
|
||||
]
|
||||
|
||||
# List of default capabilities for containers. If it is empty or commented out,
|
||||
# the default capabilities defined in the container engine will be added.
|
||||
#
|
||||
default_capabilities = [
|
||||
"AUDIT_WRITE",
|
||||
"CHOWN",
|
||||
"DAC_OVERRIDE",
|
||||
"FOWNER",
|
||||
"FSETID",
|
||||
"KILL",
|
||||
"MKNOD",
|
||||
"NET_BIND_SERVICE",
|
||||
"NET_RAW",
|
||||
"SETGID",
|
||||
"SETPCAP",
|
||||
"SETUID",
|
||||
"SYS_CHROOT",
|
||||
]
|
||||
93
tests/containers_conf.bats
Normal file
93
tests/containers_conf.bats
Normal file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load helpers
|
||||
|
||||
@test "containers.conf env test" {
|
||||
export CONTAINERS_CONF=${TESTSDIR}/containers.conf
|
||||
cid=$(buildah from --pull --signature-policy ${TESTSDIR}/policy.json docker.io/alpine)
|
||||
run_buildah --log-level=error run $cid sh -c 'env | grep "foo=bar"'
|
||||
}
|
||||
|
||||
@test "containers.conf selinux test" {
|
||||
if ! which selinuxenabled > /dev/null 2> /dev/null ; then
|
||||
skip "No selinuxenabled executable"
|
||||
elif ! selinuxenabled ; then
|
||||
skip "selinux is disabled"
|
||||
fi
|
||||
|
||||
|
||||
export CONTAINERS_CONF=${TESTSDIR}/containers.conf
|
||||
cid=$(buildah from --pull --signature-policy ${TESTSDIR}/policy.json docker.io/alpine)
|
||||
run_buildah --log-level=error run $cid sh -c "cat /proc/self/attr/current | grep container_t"
|
||||
|
||||
buildah rm $cid
|
||||
|
||||
export CONTAINERS_CONF=${TESTSDIR}/containers1.conf
|
||||
sed "s/^label = true/label = false/g" ${TESTSDIR}/containers.conf > ${TESTSDIR}/containers1.conf
|
||||
cid=$(buildah from --pull --signature-policy ${TESTSDIR}/policy.json docker.io/alpine)
|
||||
run_buildah 1 --log-level=error run $cid sh -c "cat /proc/self/attr/current | grep container_t"
|
||||
rm ${TESTSDIR}/containers1.conf
|
||||
}
|
||||
|
||||
@test "containers.conf ulimit test" {
|
||||
if test "$BUILDAH_ISOLATION" = "chroot" -o "$BUILDAH_ISOLATION" = "rootless" ; then
|
||||
skip "BUILDAH_ISOLATION = $BUILDAH_ISOLATION"
|
||||
fi
|
||||
|
||||
export CONTAINERS_CONF=${TESTSDIR}/containers.conf
|
||||
cid=$(buildah from --pull --signature-policy ${TESTSDIR}/policy.json docker.io/alpine)
|
||||
run_buildah --log-level=error run $cid awk '/open files/{print $4}' /proc/self/limits
|
||||
expect_output "500" "limits: open files (w/file limit)"
|
||||
|
||||
cid=$(buildah from --pull --ulimit nofile=300:400 --signature-policy ${TESTSDIR}/policy.json docker.io/alpine)
|
||||
run_buildah --log-level=error run $cid awk '/open files/{print $4}' /proc/self/limits
|
||||
expect_output "300" "limits: open files (w/file limit)"
|
||||
}
|
||||
|
||||
@test "containers.conf additional devices test" {
|
||||
if test "$BUILDAH_ISOLATION" = "chroot" -o "$BUILDAH_ISOLATION" = "rootless" ; then
|
||||
skip "BUILDAH_ISOLATION = $BUILDAH_ISOLATION"
|
||||
fi
|
||||
export CONTAINERS_CONF=${TESTSDIR}/containers.conf
|
||||
cid=$(buildah from --pull --signature-policy ${TESTSDIR}/policy.json docker.io/alpine)
|
||||
run_buildah 1 --log-level=error run $cid ls /dev/foo1
|
||||
buildah rm $cid
|
||||
|
||||
sed '/additional_devices.*/a "/dev/foo:\/dev\/foo1:rmw",' ${TESTSDIR}/containers.conf > ${TESTSDIR}/containers1.conf
|
||||
rm -f /dev/foo; mknod /dev/foo c 1 1
|
||||
export CONTAINERS_CONF=${TESTSDIR}/containers1.conf
|
||||
cid=$(buildah from --pull --signature-policy ${TESTSDIR}/policy.json docker.io/alpine)
|
||||
run_buildah --log-level=error run $cid ls /dev/foo1
|
||||
rm -f /dev/foo
|
||||
rm ${TESTSDIR}/containers1.conf
|
||||
}
|
||||
|
||||
@test "containers.conf capabilities test" {
|
||||
export CONTAINERS_CONF=${TESTSDIR}/containers.conf
|
||||
cid=$(buildah from --pull --signature-policy ${TESTSDIR}/policy.json docker.io/alpine)
|
||||
run_buildah --log-level=error run $cid sh -c 'grep CapEff /proc/self/status | cut -f2'
|
||||
CapEff=$output
|
||||
expect_output "00000000280425fb"
|
||||
buildah rm $cid
|
||||
|
||||
sed "/AUDIT_WRITE/d" ${TESTSDIR}/containers.conf > ${TESTSDIR}/containers1.conf
|
||||
export CONTAINERS_CONF=${TESTSDIR}/containers1.conf
|
||||
cid=$(buildah from --pull --signature-policy ${TESTSDIR}/policy.json docker.io/alpine)
|
||||
|
||||
run_buildah --log-level=error run $cid sh -c 'grep CapEff /proc/self/status | cut -f2'
|
||||
buildah rm $cid
|
||||
|
||||
test "$output" != "$CapEff"
|
||||
rm ${TESTSDIR}/containers1.conf
|
||||
}
|
||||
|
||||
@test "containers.conf /dev/shm test" {
|
||||
if test "$BUILDAH_ISOLATION" = "chroot" -o "$BUILDAH_ISOLATION" = "rootless" ; then
|
||||
skip "BUILDAH_ISOLATION = $BUILDAH_ISOLATION"
|
||||
fi
|
||||
|
||||
export CONTAINERS_CONF=${TESTSDIR}/containers.conf
|
||||
cid=$(buildah from --pull --signature-policy ${TESTSDIR}/policy.json docker.io/alpine)
|
||||
run_buildah --log-level=error run $cid sh -c 'df /dev/shm | awk '\''/shm/{print $4}'\'''
|
||||
expect_output "200"
|
||||
}
|
||||
173
vendor/github.com/containers/common/pkg/caps/caps.go
generated
vendored
Normal file
173
vendor/github.com/containers/common/pkg/caps/caps.go
generated
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
package caps // originally imported "github.com/docker/docker/oci/caps"
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/syndtr/gocapability/capability"
|
||||
)
|
||||
|
||||
var (
|
||||
capabilityList Capabilities
|
||||
|
||||
// InvalidCapability indicates the caller specified invalid capability
|
||||
InvalidCapability = errors.New("invalid capability")
|
||||
)
|
||||
|
||||
func init() {
|
||||
last := capability.CAP_LAST_CAP
|
||||
// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
|
||||
if last == capability.Cap(63) {
|
||||
last = capability.CAP_BLOCK_SUSPEND
|
||||
}
|
||||
for _, cap := range capability.List() {
|
||||
if cap > last {
|
||||
continue
|
||||
}
|
||||
capabilityList = append(capabilityList,
|
||||
&CapabilityMapping{
|
||||
Key: "CAP_" + strings.ToUpper(cap.String()),
|
||||
Value: cap,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
// CapabilityMapping maps linux capability name to its value of capability.Cap type
|
||||
// Capabilities is one of the security systems in Linux Security Module (LSM)
|
||||
// framework provided by the kernel.
|
||||
// For more details on capabilities, see http://man7.org/linux/man-pages/man7/capabilities.7.html
|
||||
CapabilityMapping struct {
|
||||
Key string `json:"key,omitempty"`
|
||||
Value capability.Cap `json:"value,omitempty"`
|
||||
}
|
||||
// Capabilities contains all CapabilityMapping
|
||||
Capabilities []*CapabilityMapping
|
||||
)
|
||||
|
||||
// String returns <key> of CapabilityMapping
|
||||
func (c *CapabilityMapping) String() string {
|
||||
return c.Key
|
||||
}
|
||||
|
||||
// GetCapability returns CapabilityMapping which contains specific key
|
||||
func GetCapability(key string) *CapabilityMapping {
|
||||
for _, capp := range capabilityList {
|
||||
if capp.Key == key {
|
||||
cpy := *capp
|
||||
return &cpy
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAllCapabilities returns all of the capabilities
|
||||
func GetAllCapabilities() []string {
|
||||
output := make([]string, len(capabilityList))
|
||||
for i, capability := range capabilityList {
|
||||
output[i] = capability.String()
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
// inSlice tests whether a string is contained in a slice of strings or not.
|
||||
func inSlice(slice []string, s string) bool {
|
||||
for _, ss := range slice {
|
||||
if s == ss {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const allCapabilities = "ALL"
|
||||
|
||||
// NormalizeLegacyCapabilities normalizes, and validates CapAdd/CapDrop capabilities
|
||||
// by upper-casing them, and adding a CAP_ prefix (if not yet present).
|
||||
//
|
||||
// This function also accepts the "ALL" magic-value, that's used by CapAdd/CapDrop.
|
||||
func NormalizeLegacyCapabilities(caps []string) ([]string, error) {
|
||||
var normalized []string
|
||||
|
||||
valids := GetAllCapabilities()
|
||||
for _, c := range caps {
|
||||
c = strings.ToUpper(c)
|
||||
if c == allCapabilities {
|
||||
normalized = append(normalized, c)
|
||||
continue
|
||||
}
|
||||
if !strings.HasPrefix(c, "CAP_") {
|
||||
c = "CAP_" + c
|
||||
}
|
||||
if !inSlice(valids, c) {
|
||||
return nil, errors.Wrap(InvalidCapability, c)
|
||||
}
|
||||
normalized = append(normalized, c)
|
||||
}
|
||||
return normalized, nil
|
||||
}
|
||||
|
||||
// ValidateCapabilities validates if caps only contains valid capabilities
|
||||
func ValidateCapabilities(caps []string) error {
|
||||
valids := GetAllCapabilities()
|
||||
for _, c := range caps {
|
||||
if !inSlice(valids, c) {
|
||||
return errors.Wrap(InvalidCapability, c)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TweakCapabilities tweaks capabilities by adding, dropping, or overriding
|
||||
// capabilities in the basics capabilities list.
|
||||
func TweakCapabilities(basics, adds, drops, capabilities []string, privileged bool) ([]string, error) {
|
||||
switch {
|
||||
case privileged:
|
||||
// Privileged containers get all capabilities
|
||||
return GetAllCapabilities(), nil
|
||||
case capabilities != nil:
|
||||
// Use custom set of capabilities
|
||||
if err := ValidateCapabilities(capabilities); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return capabilities, nil
|
||||
case len(adds) == 0 && len(drops) == 0:
|
||||
// Nothing to tweak; we're done
|
||||
return basics, nil
|
||||
}
|
||||
|
||||
capDrop, err := NormalizeLegacyCapabilities(drops)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
capAdd, err := NormalizeLegacyCapabilities(adds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var caps []string
|
||||
|
||||
switch {
|
||||
case inSlice(capAdd, allCapabilities):
|
||||
// Add all capabilities except ones on capDrop
|
||||
for _, c := range GetAllCapabilities() {
|
||||
if !inSlice(capDrop, c) {
|
||||
caps = append(caps, c)
|
||||
}
|
||||
}
|
||||
case inSlice(capDrop, allCapabilities):
|
||||
// "Drop" all capabilities; use what's in capAdd instead
|
||||
caps = capAdd
|
||||
default:
|
||||
// First drop some capabilities
|
||||
for _, c := range basics {
|
||||
if !inSlice(capDrop, c) {
|
||||
caps = append(caps, c)
|
||||
}
|
||||
}
|
||||
// Then add the list of capabilities from capAdd
|
||||
caps = append(caps, capAdd...)
|
||||
}
|
||||
return caps, nil
|
||||
}
|
||||
847
vendor/github.com/containers/common/pkg/config/config.go
generated
vendored
Normal file
847
vendor/github.com/containers/common/pkg/config/config.go
generated
vendored
Normal file
@@ -0,0 +1,847 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/containers/common/pkg/caps"
|
||||
"github.com/containers/common/pkg/unshare"
|
||||
"github.com/containers/storage"
|
||||
units "github.com/docker/go-units"
|
||||
selinux "github.com/opencontainers/selinux/go-selinux"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultContainersConfig holds the default containers config path
|
||||
DefaultContainersConfig = "/usr/share/containers/containers.conf"
|
||||
// OverrideContainersConfig holds the default config paths overridden by the root user
|
||||
OverrideContainersConfig = "/etc/containers/containers.conf"
|
||||
// UserOverrideContainersConfig holds the containers config path overridden by the rootless user
|
||||
UserOverrideContainersConfig = ".config/containers/containers.conf"
|
||||
)
|
||||
|
||||
// RuntimeStateStore is a constant indicating which state store implementation
|
||||
// should be used by libpod
|
||||
type RuntimeStateStore int
|
||||
|
||||
const (
|
||||
// InvalidStateStore is an invalid state store
|
||||
InvalidStateStore RuntimeStateStore = iota
|
||||
// InMemoryStateStore is an in-memory state that will not persist data
|
||||
// on containers and pods between libpod instances or after system
|
||||
// reboot
|
||||
InMemoryStateStore RuntimeStateStore = iota
|
||||
// SQLiteStateStore is a state backed by a SQLite database
|
||||
// It is presently disabled
|
||||
SQLiteStateStore RuntimeStateStore = iota
|
||||
// BoltDBStateStore is a state backed by a BoltDB database
|
||||
BoltDBStateStore RuntimeStateStore = iota
|
||||
)
|
||||
|
||||
// Config contains configuration options for container tools
|
||||
type Config struct {
|
||||
// Containers specify settings that configure how containers will run ont the system
|
||||
Containers ContainersConfig `toml:"containers"`
|
||||
// Libpod specifies how the container engine based on Libpod will run
|
||||
Libpod LibpodConfig `toml:"libpod"`
|
||||
// Network section defines the configuration of CNI Plugins
|
||||
Network NetworkConfig `toml:"network"`
|
||||
}
|
||||
|
||||
// ContainersConfig represents the "containers" TOML config table
|
||||
// containers global options for containers tools
|
||||
type ContainersConfig struct {
|
||||
|
||||
// Devices to add to all containers
|
||||
AdditionalDevices []string `toml:"additional_devices"`
|
||||
|
||||
// Volumes to add to all containers
|
||||
AdditionalVolumes []string `toml:"additional_volumes"`
|
||||
|
||||
// ApparmorProfile is the apparmor profile name which is used as the
|
||||
// default for the runtime.
|
||||
ApparmorProfile string `toml:"apparmor_profile"`
|
||||
|
||||
// CGroupManager is the CGroup Manager to use Valid values are "cgroupfs"
|
||||
// and "systemd".
|
||||
CgroupManager string `toml:"cgroup_manager"`
|
||||
|
||||
// Default way to create a cgroup namespace for the container
|
||||
CgroupNS string `toml:"cgroupns"`
|
||||
|
||||
// Capabilities to add to all containers.
|
||||
DefaultCapabilities []string `toml:"default_capabilities"`
|
||||
|
||||
// Sysctls to add to all containers.
|
||||
DefaultSysctls []string `toml:"default_sysctls"`
|
||||
|
||||
// DefaultUlimits specifies the default ulimits to apply to containers
|
||||
DefaultUlimits []string `toml:"default_ulimits"`
|
||||
|
||||
// DefaultMountsFile is the path to the default mounts file for testing
|
||||
DefaultMountsFile string `toml:"-"`
|
||||
|
||||
// DNSServers set default DNS servers.
|
||||
DNSServers []string `toml:"dns_servers"`
|
||||
|
||||
// DNSOptions set default DNS options.
|
||||
DNSOptions []string `toml:"dns_options"`
|
||||
|
||||
// DNSSearches set default DNS search domains.
|
||||
DNSSearches []string `toml:"dns_searches"`
|
||||
|
||||
// EnableLabeling tells the container engines whether to use MAC
|
||||
// Labeling to separate containers (SELinux)
|
||||
EnableLabeling bool `toml:"label"`
|
||||
|
||||
// Env is the environment variable list for container process.
|
||||
Env []string `toml:"env"`
|
||||
|
||||
// EnvHost Pass all host environment variables into the container.
|
||||
EnvHost bool `toml:"env_host"`
|
||||
|
||||
// HTTPProxy is the proxy environment variable list to apply to container process
|
||||
HTTPProxy bool `toml:"http_proxy"`
|
||||
|
||||
// Init tells container runtimes whether to run init inside the
|
||||
// container that forwards signals and reaps processes.
|
||||
Init bool `toml:"init"`
|
||||
|
||||
// InitPath is the path for init to run if the Init bool is enabled
|
||||
InitPath string `toml:"init_path"`
|
||||
|
||||
// IPCNS way to to create a ipc namespace for the container
|
||||
IPCNS string `toml:"ipcns"`
|
||||
|
||||
// LogDriver for the container. For example: k8s-file and journald
|
||||
LogDriver string `toml:"log_driver"`
|
||||
|
||||
// LogSizeMax is the maximum number of bytes after which the log file
|
||||
// will be truncated. It can be expressed as a human-friendly string
|
||||
// that is parsed to bytes.
|
||||
// Negative values indicate that the log file won't be truncated.
|
||||
LogSizeMax int64 `toml:"log_size_max"`
|
||||
|
||||
// NetNS indicates how to create a network namespace for the container
|
||||
NetNS string `toml:"netns"`
|
||||
|
||||
// NoHosts tells container engine whether to create its own /etc/hosts
|
||||
NoHosts bool `toml:"no_hosts"`
|
||||
|
||||
// PidsLimit is the number of processes each container is restricted to
|
||||
// by the cgroup process number controller.
|
||||
PidsLimit int64 `toml:"pids_limit"`
|
||||
|
||||
// PidNS indicates how to create a pid namespace for the container
|
||||
PidNS string `toml:"pidns"`
|
||||
|
||||
// SeccompProfile is the seccomp.json profile path which is used as the
|
||||
// default for the runtime.
|
||||
SeccompProfile string `toml:"seccomp_profile"`
|
||||
|
||||
// ShmSize holds the size of /dev/shm.
|
||||
ShmSize string `toml:"shm_size"`
|
||||
|
||||
// SignaturePolicyPath is the path to a signature policy to use for
|
||||
// validating images. If left empty, the containers/image default signature
|
||||
// policy will be used.
|
||||
SignaturePolicyPath string `toml:"_"`
|
||||
|
||||
// UTSNS indicates how to create a UTS namespace for the container
|
||||
UTSNS string `toml:"utsns"`
|
||||
|
||||
// UserNS indicates how to create a User namespace for the container
|
||||
UserNS string `toml:"userns"`
|
||||
|
||||
// UserNSSize how many UIDs to allocate for automatically created UserNS
|
||||
UserNSSize int `toml:"userns_size"`
|
||||
}
|
||||
|
||||
// LibpodConfig contains configuration options used to set up a libpod runtime
|
||||
type LibpodConfig struct {
|
||||
// NOTE: when changing this struct, make sure to update (*Config).Merge().
|
||||
|
||||
// ConmonEnvVars are environment variables to pass to the Conmon binary
|
||||
// when it is launched.
|
||||
ConmonEnvVars []string `toml:"conmon_env_vars"`
|
||||
|
||||
// ConmonPath is the path to the Conmon binary used for managing containers.
|
||||
// The first path pointing to a valid file will be used.
|
||||
ConmonPath []string `toml:"conmon_path"`
|
||||
|
||||
//DetachKeys is the sequence of keys used to detach a container.
|
||||
DetachKeys string `toml:"detach_keys"`
|
||||
|
||||
// EnablePortReservation determines whether libpod will reserve ports on the
|
||||
// host when they are forwarded to containers. When enabled, when ports are
|
||||
// forwarded to containers, they are held open by conmon as long as the
|
||||
// container is running, ensuring that they cannot be reused by other
|
||||
// programs on the host. However, this can cause significant memory usage if
|
||||
// a container has many ports forwarded to it. Disabling this can save
|
||||
// memory.
|
||||
EnablePortReservation bool `toml:"enable_port_reservation"`
|
||||
|
||||
// EventsLogFilePath is where the events log is stored.
|
||||
EventsLogFilePath string `toml:"events_logfile_path"`
|
||||
|
||||
// EventsLogger determines where events should be logged.
|
||||
EventsLogger string `toml:"events_logger"`
|
||||
|
||||
// configuration files. When the same filename is present in in
|
||||
// multiple directories, the file in the directory listed last in
|
||||
// this slice takes precedence.
|
||||
HooksDir []string `toml:"hooks_dir"`
|
||||
|
||||
// ImageDefaultTransport is the default transport method used to fetch
|
||||
// images.
|
||||
ImageDefaultTransport string `toml:"image_default_transport"`
|
||||
|
||||
// InfraCommand is the command run to start up a pod infra container.
|
||||
InfraCommand string `toml:"infra_command"`
|
||||
|
||||
// InfraImage is the image a pod infra container will use to manage
|
||||
// namespaces.
|
||||
InfraImage string `toml:"infra_image"`
|
||||
|
||||
// InitPath is the path to the container-init binary.
|
||||
InitPath string `toml:"init_path"`
|
||||
|
||||
// LockType is the type of locking to use.
|
||||
LockType string `toml:"lock_type,omitempty"`
|
||||
|
||||
// Namespace is the libpod namespace to use. Namespaces are used to create
|
||||
// scopes to separate containers and pods in the state. When namespace is
|
||||
// set, libpod will only view containers and pods in the same namespace. All
|
||||
// containers and pods created will default to the namespace set here. A
|
||||
// namespace of "", the empty string, is equivalent to no namespace, and all
|
||||
// containers and pods will be visible. The default namespace is "".
|
||||
Namespace string `toml:"namespace,omitempty"`
|
||||
|
||||
// NetworkCmdPath is the path to the slirp4netns binary.
|
||||
NetworkCmdPath string `toml:"network_cmd_path"`
|
||||
|
||||
// NoPivotRoot sets whether to set no-pivot-root in the OCI runtime.
|
||||
NoPivotRoot bool `toml:"no_pivot_root"`
|
||||
|
||||
// NumLocks is the number of locks to make available for containers and
|
||||
// pods.
|
||||
NumLocks uint32 `toml:"num_locks,omitempty"`
|
||||
|
||||
// OCIRuntime is the OCI runtime to use.
|
||||
OCIRuntime string `toml:"runtime"`
|
||||
|
||||
// OCIRuntimes are the set of configured OCI runtimes (default is runc).
|
||||
OCIRuntimes map[string][]string `toml:"runtimes"`
|
||||
|
||||
// RuntimeSupportsJSON is the list of the OCI runtimes that support
|
||||
// --format=json.
|
||||
RuntimeSupportsJSON []string `toml:"runtime_supports_json"`
|
||||
|
||||
// RuntimeSupportsNoCgroups is a list of OCI runtimes that support
|
||||
// running containers without CGroups.
|
||||
RuntimeSupportsNoCgroups []string `toml:"runtime_supports_nocgroups"`
|
||||
|
||||
// SetOptions contains a subset of config options. It's used to indicate if
|
||||
// a given option has either been set by the user or by a parsed libpod
|
||||
// configuration file. If not, the corresponding option might be
|
||||
// overwritten by values from the database. This behavior guarantess
|
||||
// backwards compat with older version of libpod and Podman.
|
||||
SetOptions
|
||||
|
||||
// SDNotify tells container engine to allow containers to notify the host systemd of
|
||||
// readiness using the SD_NOTIFY mechanism.
|
||||
SDNotify bool
|
||||
|
||||
// StateType is the type of the backing state store. Avoid using multiple
|
||||
// values for this with the same containers/storage configuration on the
|
||||
// same system. Different state types do not interact, and each will see a
|
||||
// separate set of containers, which may cause conflicts in
|
||||
// containers/storage. As such this is not exposed via the config file.
|
||||
StateType RuntimeStateStore `toml:"-"`
|
||||
|
||||
// StaticDir is the path to a persistent directory to store container
|
||||
// files.
|
||||
StaticDir string `toml:"static_dir"`
|
||||
|
||||
// StorageConfig is the configuration used by containers/storage Not
|
||||
// included in the on-disk config, use the dedicated containers/storage
|
||||
// configuration file instead.
|
||||
StorageConfig storage.StoreOptions `toml:"-"`
|
||||
|
||||
// TmpDir is the path to a temporary directory to store per-boot container
|
||||
// files. Must be stored in a tmpfs.
|
||||
TmpDir string `toml:"tmp_dir"`
|
||||
|
||||
// VolumePath is the default location that named volumes will be created
|
||||
// under. This convention is followed by the default volume driver, but
|
||||
// may not be by other drivers.
|
||||
VolumePath string `toml:"volume_path"`
|
||||
}
|
||||
|
||||
// SetOptions contains a subset of options in a Config. It's used to indicate if
|
||||
// a given option has either been set by the user or by a parsed libpod
|
||||
// configuration file. If not, the corresponding option might be overwritten by
|
||||
// values from the database. This behavior guarantess backwards compat with
|
||||
// older version of libpod and Podman.
|
||||
type SetOptions struct {
|
||||
// StorageConfigRunRootSet indicates if the RunRoot has been explicitly set
|
||||
// by the config or by the user. It's required to guarantee backwards
|
||||
// compatibility with older versions of libpod for which we must query the
|
||||
// database configuration. Not included in the on-disk config.
|
||||
StorageConfigRunRootSet bool `toml:"-"`
|
||||
|
||||
// StorageConfigGraphRootSet indicates if the RunRoot has been explicitly
|
||||
// set by the config or by the user. It's required to guarantee backwards
|
||||
// compatibility with older versions of libpod for which we must query the
|
||||
// database configuration. Not included in the on-disk config.
|
||||
StorageConfigGraphRootSet bool `toml:"-"`
|
||||
|
||||
// StorageConfigGraphDriverNameSet indicates if the GraphDriverName has been
|
||||
// explicitly set by the config or by the user. It's required to guarantee
|
||||
// backwards compatibility with older versions of libpod for which we must
|
||||
// query the database configuration. Not included in the on-disk config.
|
||||
StorageConfigGraphDriverNameSet bool `toml:"-"`
|
||||
|
||||
// StaticDirSet indicates if the StaticDir has been explicitly set by the
|
||||
// config or by the user. It's required to guarantee backwards compatibility
|
||||
// with older versions of libpod for which we must query the database
|
||||
// configuration. Not included in the on-disk config.
|
||||
StaticDirSet bool `toml:"-"`
|
||||
|
||||
// VolumePathSet indicates if the VolumePath has been explicitly set by the
|
||||
// config or by the user. It's required to guarantee backwards compatibility
|
||||
// with older versions of libpod for which we must query the database
|
||||
// configuration. Not included in the on-disk config.
|
||||
VolumePathSet bool `toml:"-"`
|
||||
|
||||
// TmpDirSet indicates if the TmpDir has been explicitly set by the config
|
||||
// or by the user. It's required to guarantee backwards compatibility with
|
||||
// older versions of libpod for which we must query the database
|
||||
// configuration. Not included in the on-disk config.
|
||||
TmpDirSet bool `toml:"-"`
|
||||
}
|
||||
|
||||
// NetworkConfig represents the "network" TOML config table
|
||||
type NetworkConfig struct {
|
||||
// CNIPluginDirs is where CNI plugin binaries are stored.
|
||||
CNIPluginDirs []string `toml:"cni_plugin_dirs"`
|
||||
|
||||
// DefaultNetwork is the network name of the default CNI network
|
||||
// to attach pods to.
|
||||
DefaultNetwork string `toml:"default_network,omitempty"`
|
||||
|
||||
// NetworkConfigDir is where CNI network configuration files are stored.
|
||||
NetworkConfigDir string `toml:"network_config_dir"`
|
||||
}
|
||||
|
||||
// NewConfig creates a new Config. It starts with an empty config and, if
|
||||
// specified, merges the config at `userConfigPath` path. Depending if we're
|
||||
// running as root or rootless, we then merge the system configuration followed
|
||||
// by merging the default config (hard-coded default in memory).
|
||||
// Note that the OCI runtime is hard-set to `crun` if we're running on a system
|
||||
// with cgroupsv2. Other OCI runtimes are not yet supporting cgroupsv2. This
|
||||
// might change in the future.
|
||||
func NewConfig(userConfigPath string) (*Config, error) {
|
||||
|
||||
// Genereate the default config for the system
|
||||
config, err := DefaultConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If the caller specified a config path to use, then we read this
|
||||
// rather then using the system defaults.
|
||||
if userConfigPath != "" {
|
||||
var err error
|
||||
// ReadConfigFromFile reads in container config in the specified
|
||||
// file and then merge changes with the current defauls.
|
||||
config, err = ReadConfigFromFile(userConfigPath, config)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error reading user config %q", userConfigPath)
|
||||
}
|
||||
}
|
||||
|
||||
// Now, gather the system configs and merge them as needed.
|
||||
configs, err := systemConfigs()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error finding config on system")
|
||||
}
|
||||
for _, path := range configs {
|
||||
// Merge changes in later configs with the previous configs.
|
||||
// Each config file that specified fields, will override the
|
||||
// previous fields.
|
||||
config, err := ReadConfigFromFile(path, config)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error reading system config %q", path)
|
||||
}
|
||||
logrus.Debugf("Merged system config %q: %v", path, config)
|
||||
}
|
||||
|
||||
config.checkCgroupsAndAdjustConfig()
|
||||
config.addCAPPrefix()
|
||||
|
||||
if err := config.Validate(true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// ReadConfigFromFile reads the specified config file at `path` and attempts to
|
||||
// unmarshal its content into a Config. The config param specifies the previos
|
||||
// default config. If the path, only specifies a few fields in the Toml file
|
||||
// the defaults from the config paramater will be used for all other fields.
|
||||
func ReadConfigFromFile(path string, config *Config) (*Config, error) {
|
||||
logrus.Debugf("Reading configuration file %q", path)
|
||||
_, err := toml.DecodeFile(path, config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to decode configuration %v: %v", path, err)
|
||||
}
|
||||
if config.Libpod.VolumePath != "" {
|
||||
config.Libpod.VolumePathSet = true
|
||||
}
|
||||
if config.Libpod.StaticDir != "" {
|
||||
config.Libpod.StaticDirSet = true
|
||||
}
|
||||
if config.Libpod.TmpDir != "" {
|
||||
config.Libpod.TmpDirSet = true
|
||||
}
|
||||
|
||||
return config, err
|
||||
}
|
||||
|
||||
// Returns the list of configuration files, if they exist in order of hierarchy.
|
||||
// The files are read in order and each new file can/will override previous
|
||||
// file settings.
|
||||
func systemConfigs() ([]string, error) {
|
||||
configs := []string{}
|
||||
path := os.Getenv("CONTAINERS_CONF")
|
||||
if path != "" {
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to stat of %s from CONTAINERS_CONF environment variable")
|
||||
}
|
||||
return append(configs, path), nil
|
||||
}
|
||||
if _, err := os.Stat(DefaultContainersConfig); err == nil {
|
||||
configs = append(configs, DefaultContainersConfig)
|
||||
}
|
||||
if _, err := os.Stat(OverrideContainersConfig); err == nil {
|
||||
configs = append(configs, OverrideContainersConfig)
|
||||
}
|
||||
if unshare.IsRootless() {
|
||||
path, err := rootlessConfigPath()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
configs = append(configs, path)
|
||||
}
|
||||
}
|
||||
return configs, nil
|
||||
}
|
||||
|
||||
// checkCgroupsAndAdjustConfig checks if we're running rootless with the systemd
|
||||
// cgroup manager. In case the user session isn't available, we're switching the
|
||||
// cgroup manager to cgroupfs. Note, this only applies to rootless.
|
||||
func (c *Config) checkCgroupsAndAdjustConfig() {
|
||||
if !unshare.IsRootless() || c.Containers.CgroupManager != SystemdCgroupsManager {
|
||||
return
|
||||
}
|
||||
|
||||
session := os.Getenv("DBUS_SESSION_BUS_ADDRESS")
|
||||
hasSession := session != ""
|
||||
if hasSession && strings.HasPrefix(session, "unix:path=") {
|
||||
_, err := os.Stat(strings.TrimPrefix(session, "unix:path="))
|
||||
hasSession = err == nil
|
||||
}
|
||||
|
||||
if !hasSession {
|
||||
logrus.Warningf("The cgroups manager is set to systemd but there is no systemd user session available")
|
||||
logrus.Warningf("For using systemd, you may need to login using an user session")
|
||||
logrus.Warningf("Alternatively, you can enable lingering with: `loginctl enable-linger %d` (possibly as root)", unshare.GetRootlessUID())
|
||||
logrus.Warningf("Falling back to --cgroup-manager=cgroupfs")
|
||||
c.Containers.CgroupManager = CgroupfsCgroupsManager
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) addCAPPrefix() {
|
||||
toCAPPrefixed := func(cap string) string {
|
||||
if !strings.HasPrefix(strings.ToLower(cap), "cap_") {
|
||||
return "CAP_" + strings.ToUpper(cap)
|
||||
}
|
||||
return cap
|
||||
}
|
||||
for i, cap := range c.Containers.DefaultCapabilities {
|
||||
c.Containers.DefaultCapabilities[i] = toCAPPrefixed(cap)
|
||||
}
|
||||
}
|
||||
|
||||
// Validate is the main entry point for library configuration validation.
|
||||
// The parameter `onExecution` specifies if the validation should include
|
||||
// execution checks. It returns an `error` on validation failure, otherwise
|
||||
// `nil`.
|
||||
func (c *Config) Validate(onExecution bool) error {
|
||||
|
||||
if err := c.Containers.Validate(); err != nil {
|
||||
return errors.Wrapf(err, "containers config")
|
||||
}
|
||||
|
||||
if !unshare.IsRootless() {
|
||||
if err := c.Network.Validate(onExecution); err != nil {
|
||||
return errors.Wrapf(err, "network config")
|
||||
}
|
||||
}
|
||||
if !c.Containers.EnableLabeling {
|
||||
selinux.SetDisabled()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate is the main entry point for Libpod configuration validation
|
||||
// It returns an `error` on validation failure, otherwise
|
||||
// `nil`.
|
||||
func (c *LibpodConfig) Validate() error {
|
||||
// Relative paths can cause nasty bugs, because core paths we use could
|
||||
// shift between runs (or even parts of the program - the OCI runtime
|
||||
// uses a different working directory than we do, for example.
|
||||
if !filepath.IsAbs(c.StaticDir) {
|
||||
return fmt.Errorf("static directory must be an absolute path - instead got %q", c.StaticDir)
|
||||
}
|
||||
if !filepath.IsAbs(c.TmpDir) {
|
||||
return fmt.Errorf("temporary directory must be an absolute path - instead got %q", c.TmpDir)
|
||||
}
|
||||
if !filepath.IsAbs(c.VolumePath) {
|
||||
return fmt.Errorf("volume path must be an absolute path - instead got %q", c.VolumePath)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate is the main entry point for containers configuration validation
|
||||
// It returns an `error` on validation failure, otherwise
|
||||
// `nil`.
|
||||
func (c *ContainersConfig) Validate() error {
|
||||
for _, u := range c.DefaultUlimits {
|
||||
ul, err := units.ParseUlimit(u)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unrecognized ulimit %s: %v", u, err)
|
||||
}
|
||||
_, err = ul.GetRlimit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range c.AdditionalDevices {
|
||||
_, _, _, err := Device(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if c.LogSizeMax >= 0 && c.LogSizeMax < OCIBufSize {
|
||||
return fmt.Errorf("log size max should be negative or >= %d", OCIBufSize)
|
||||
}
|
||||
|
||||
if _, err := units.FromHumanSize(c.ShmSize); err != nil {
|
||||
return fmt.Errorf("invalid --shm-size %s, %q", c.ShmSize, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate is the main entry point for network configuration validation.
|
||||
// The parameter `onExecution` specifies if the validation should include
|
||||
// execution checks. It returns an `error` on validation failure, otherwise
|
||||
// `nil`.
|
||||
func (c *NetworkConfig) Validate(onExecution bool) error {
|
||||
if onExecution {
|
||||
err := IsDirectory(c.NetworkConfigDir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(c.NetworkConfigDir, 0755); err != nil {
|
||||
return errors.Wrapf(err, "Cannot create network_config_dir: %s", c.NetworkConfigDir)
|
||||
}
|
||||
} else {
|
||||
return errors.Wrapf(err, "invalid network_config_dir: %s", c.NetworkConfigDir)
|
||||
}
|
||||
}
|
||||
|
||||
for _, pluginDir := range c.CNIPluginDirs {
|
||||
if err := os.MkdirAll(pluginDir, 0755); err != nil {
|
||||
return errors.Wrapf(err, "invalid cni_plugin_dirs entry")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DBConfig is a set of Libpod runtime configuration settings that are saved in
|
||||
// a State when it is first created, and can subsequently be retrieved.
|
||||
type DBConfig struct {
|
||||
LibpodRoot string
|
||||
LibpodTmp string
|
||||
StorageRoot string
|
||||
StorageTmp string
|
||||
GraphDriver string
|
||||
VolumePath string
|
||||
}
|
||||
|
||||
// MergeDBConfig merges the configuration from the database.
|
||||
func (c *Config) MergeDBConfig(dbConfig *DBConfig) error {
|
||||
|
||||
if !c.Libpod.StorageConfigRunRootSet && dbConfig.StorageTmp != "" {
|
||||
if c.Libpod.StorageConfig.RunRoot != dbConfig.StorageTmp &&
|
||||
c.Libpod.StorageConfig.RunRoot != "" {
|
||||
logrus.Debugf("Overriding run root %q with %q from database",
|
||||
c.Libpod.StorageConfig.RunRoot, dbConfig.StorageTmp)
|
||||
}
|
||||
c.Libpod.StorageConfig.RunRoot = dbConfig.StorageTmp
|
||||
}
|
||||
|
||||
if !c.Libpod.StorageConfigGraphRootSet && dbConfig.StorageRoot != "" {
|
||||
if c.Libpod.StorageConfig.GraphRoot != dbConfig.StorageRoot &&
|
||||
c.Libpod.StorageConfig.GraphRoot != "" {
|
||||
logrus.Debugf("Overriding graph root %q with %q from database",
|
||||
c.Libpod.StorageConfig.GraphRoot, dbConfig.StorageRoot)
|
||||
}
|
||||
c.Libpod.StorageConfig.GraphRoot = dbConfig.StorageRoot
|
||||
}
|
||||
|
||||
if !c.Libpod.StorageConfigGraphDriverNameSet && dbConfig.GraphDriver != "" {
|
||||
if c.Libpod.StorageConfig.GraphDriverName != dbConfig.GraphDriver &&
|
||||
c.Libpod.StorageConfig.GraphDriverName != "" {
|
||||
logrus.Errorf("User-selected graph driver %q overwritten by graph driver %q from database - delete libpod local files to resolve",
|
||||
c.Libpod.StorageConfig.GraphDriverName, dbConfig.GraphDriver)
|
||||
}
|
||||
c.Libpod.StorageConfig.GraphDriverName = dbConfig.GraphDriver
|
||||
}
|
||||
|
||||
if !c.Libpod.StaticDirSet && dbConfig.LibpodRoot != "" {
|
||||
if c.Libpod.StaticDir != dbConfig.LibpodRoot && c.Libpod.StaticDir != "" {
|
||||
logrus.Debugf("Overriding static dir %q with %q from database", c.Libpod.StaticDir, dbConfig.LibpodRoot)
|
||||
}
|
||||
c.Libpod.StaticDir = dbConfig.LibpodRoot
|
||||
}
|
||||
|
||||
if !c.Libpod.TmpDirSet && dbConfig.LibpodTmp != "" {
|
||||
if c.Libpod.TmpDir != dbConfig.LibpodTmp && c.Libpod.TmpDir != "" {
|
||||
logrus.Debugf("Overriding tmp dir %q with %q from database", c.Libpod.TmpDir, dbConfig.LibpodTmp)
|
||||
}
|
||||
c.Libpod.TmpDir = dbConfig.LibpodTmp
|
||||
c.Libpod.EventsLogFilePath = filepath.Join(dbConfig.LibpodTmp, "events", "events.log")
|
||||
}
|
||||
|
||||
if !c.Libpod.VolumePathSet && dbConfig.VolumePath != "" {
|
||||
if c.Libpod.VolumePath != dbConfig.VolumePath && c.Libpod.VolumePath != "" {
|
||||
logrus.Debugf("Overriding volume path %q with %q from database", c.Libpod.VolumePath, dbConfig.VolumePath)
|
||||
}
|
||||
c.Libpod.VolumePath = dbConfig.VolumePath
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindConmon iterates over (*Config).ConmonPath and returns the path to first
|
||||
// (version) matching conmon binary. If non is found, we try to do a path lookup
|
||||
// of "conmon".
|
||||
func (c *Config) FindConmon() (string, error) {
|
||||
foundOutdatedConmon := false
|
||||
for _, path := range c.Libpod.ConmonPath {
|
||||
stat, err := os.Stat(path)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if stat.IsDir() {
|
||||
continue
|
||||
}
|
||||
if err := probeConmon(path); err != nil {
|
||||
logrus.Warnf("Conmon at %s invalid: %v", path, err)
|
||||
foundOutdatedConmon = true
|
||||
continue
|
||||
}
|
||||
logrus.Debugf("Using conmon: %q", path)
|
||||
return path, nil
|
||||
}
|
||||
|
||||
// Search the $PATH as last fallback
|
||||
if path, err := exec.LookPath("conmon"); err == nil {
|
||||
if err := probeConmon(path); err != nil {
|
||||
logrus.Warnf("Conmon at %s is invalid: %v", path, err)
|
||||
foundOutdatedConmon = true
|
||||
} else {
|
||||
logrus.Debugf("Using conmon from $PATH: %q", path)
|
||||
return path, nil
|
||||
}
|
||||
}
|
||||
|
||||
if foundOutdatedConmon {
|
||||
return "", errors.Wrapf(ErrConmonOutdated,
|
||||
"please update to v%d.%d.%d or later",
|
||||
_conmonMinMajorVersion, _conmonMinMinorVersion, _conmonMinPatchVersion)
|
||||
}
|
||||
|
||||
return "", errors.Wrapf(ErrInvalidArg,
|
||||
"could not find a working conmon binary (configured options: %v)",
|
||||
c.Libpod.ConmonPath)
|
||||
}
|
||||
|
||||
// GetDefaultEnv returns the environment variables for the container.
|
||||
// It will checn the HTTPProxy and HostEnv booleans and add the appropriate
|
||||
// environment variables to the container.
|
||||
func (c *Config) GetDefaultEnv() []string {
|
||||
var env []string
|
||||
if c.Containers.EnvHost {
|
||||
env = append(env, os.Environ()...)
|
||||
} else if c.Containers.HTTPProxy {
|
||||
proxy := []string{"http_proxy", "https_proxy", "ftp_proxy", "no_proxy", "HTTP_PROXY", "HTTPS_PROXY", "FTP_PROXY", "NO_PROXY"}
|
||||
for _, p := range proxy {
|
||||
if val, ok := os.LookupEnv(p); ok {
|
||||
env = append(env, fmt.Sprintf("%s=%s", p, val))
|
||||
}
|
||||
}
|
||||
}
|
||||
return append(env, c.Containers.Env...)
|
||||
}
|
||||
|
||||
// Capabilities returns the capabilities parses the Add and Drop capability
|
||||
// list from the default capabiltiies for the container
|
||||
func (c *Config) Capabilities(user string, addCapabilities, dropCapabilities []string) []string {
|
||||
|
||||
userNotRoot := func(user string) bool {
|
||||
if user == "" || user == "root" || user == "0" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
var capabilities []string
|
||||
defaultCapabilities := c.Containers.DefaultCapabilities
|
||||
if userNotRoot(user) {
|
||||
defaultCapabilities = []string{}
|
||||
}
|
||||
|
||||
mapCap := make(map[string]bool, len(defaultCapabilities))
|
||||
for _, c := range addCapabilities {
|
||||
if strings.ToLower(c) == "all" {
|
||||
defaultCapabilities = caps.GetAllCapabilities()
|
||||
addCapabilities = nil
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, c := range append(defaultCapabilities, addCapabilities...) {
|
||||
mapCap[c] = true
|
||||
}
|
||||
for _, c := range dropCapabilities {
|
||||
if "all" == strings.ToLower(c) {
|
||||
return capabilities
|
||||
}
|
||||
mapCap[c] = false
|
||||
}
|
||||
for cap, add := range mapCap {
|
||||
if add {
|
||||
capabilities = append(capabilities, cap)
|
||||
}
|
||||
}
|
||||
return capabilities
|
||||
}
|
||||
|
||||
// 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) (string, string, string, error) {
|
||||
src := ""
|
||||
dst := ""
|
||||
permissions := "rwm"
|
||||
split := strings.Split(device, ":")
|
||||
switch len(split) {
|
||||
case 3:
|
||||
if !IsValidDeviceMode(split[2]) {
|
||||
return "", "", "", fmt.Errorf("invalid device mode: %s", split[2])
|
||||
}
|
||||
permissions = split[2]
|
||||
fallthrough
|
||||
case 2:
|
||||
if IsValidDeviceMode(split[1]) {
|
||||
permissions = split[1]
|
||||
} else {
|
||||
if len(split[1]) == 0 || split[1][0] != '/' {
|
||||
return "", "", "", fmt.Errorf("invalid device mode: %s", split[1])
|
||||
}
|
||||
dst = split[1]
|
||||
}
|
||||
fallthrough
|
||||
case 1:
|
||||
if !strings.HasPrefix(split[0], "/dev/") {
|
||||
return "", "", "", fmt.Errorf("invalid device mode: %s", split[0])
|
||||
}
|
||||
src = split[0]
|
||||
default:
|
||||
return "", "", "", fmt.Errorf("invalid device specification: %s", device)
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
// IsDirectory tests whether the given path exists and is a directory. It
|
||||
// follows symlinks.
|
||||
func IsDirectory(path string) error {
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.Mode().IsDir() {
|
||||
// Return a PathError to be consistent with os.Stat().
|
||||
return &os.PathError{
|
||||
Op: "stat",
|
||||
Path: path,
|
||||
Err: syscall.ENOTDIR,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func rootlessConfigPath() (string, error) {
|
||||
home, err := unshare.HomeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return filepath.Join(home, UserOverrideContainersConfig), nil
|
||||
}
|
||||
7
vendor/github.com/containers/common/pkg/config/config_linux.go
generated
vendored
Normal file
7
vendor/github.com/containers/common/pkg/config/config_linux.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
package config
|
||||
|
||||
import selinux "github.com/opencontainers/selinux/go-selinux"
|
||||
|
||||
func selinuxEnabled() bool {
|
||||
return selinux.GetEnabled()
|
||||
}
|
||||
15
vendor/github.com/containers/common/pkg/config/config_unix.go
generated
vendored
Normal file
15
vendor/github.com/containers/common/pkg/config/config_unix.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// +build !windows
|
||||
|
||||
package config
|
||||
|
||||
// Defaults for linux/unix if none are specified
|
||||
const (
|
||||
cniConfigDir = "/etc/cni/net.d/"
|
||||
)
|
||||
|
||||
var cniBinDir = []string{
|
||||
"/usr/libexec/cni",
|
||||
"/usr/lib/cni",
|
||||
"/usr/local/lib/cni",
|
||||
"/opt/cni/bin",
|
||||
}
|
||||
7
vendor/github.com/containers/common/pkg/config/config_unsupported.go
generated
vendored
Normal file
7
vendor/github.com/containers/common/pkg/config/config_unsupported.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// +build !linux
|
||||
|
||||
package config
|
||||
|
||||
func selinuxEnabled() bool {
|
||||
return false
|
||||
}
|
||||
10
vendor/github.com/containers/common/pkg/config/config_windows.go
generated
vendored
Normal file
10
vendor/github.com/containers/common/pkg/config/config_windows.go
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
// +build windows
|
||||
|
||||
package config
|
||||
|
||||
// Defaults for linux/unix if none are specified
|
||||
const (
|
||||
cniConfigDir = "C:\\cni\\etc\\net.d\\"
|
||||
)
|
||||
|
||||
var cniBinDir = []string{"C:\\cni\\bin\\"}
|
||||
366
vendor/github.com/containers/common/pkg/config/containers.conf
generated
vendored
Normal file
366
vendor/github.com/containers/common/pkg/config/containers.conf
generated
vendored
Normal file
@@ -0,0 +1,366 @@
|
||||
# The containers configuration file specifies all of the available configuration
|
||||
# command-line options/flags for container runtime tools like Podman & Buildah,
|
||||
# but in a TOML format that can be easily modified and versioned.
|
||||
|
||||
# Please refer to containers.conf(5) for details of all configuration options.
|
||||
# Not all container tools implement all of the options.
|
||||
# All of the options have hard coded defaults and these options will override
|
||||
# the built in defaults. Users can then override these options via the command
|
||||
# line. Container engines will read containers.conf files in up to three
|
||||
# locations in the following order:
|
||||
# 1. /usr/share/containers/containers.conf
|
||||
# 2. /etc/containers/containers.conf
|
||||
# 3. $HOME/.config/containers/containers.conf (Rootless containers ONLY)
|
||||
# Items specified in the latter containers.conf, if they exist, override the
|
||||
# previous containers.conf settings, or the default settings.
|
||||
|
||||
[containers]
|
||||
|
||||
# List of additional devices. Specified as
|
||||
# "<device-on-host>:<device-on-container>:<permissions>", for example:
|
||||
# "/dev/sdc:/dev/xvdc:rwm".
|
||||
# If it is empty or commented out, only the default devices will be used
|
||||
#
|
||||
# additional_devices = []
|
||||
|
||||
# List of additional volumes. Specified as
|
||||
# "<directory-on-host>:<directory-in-container>:<options>", for example:
|
||||
# "/db:/var/lib/db:ro".
|
||||
# If it is empty or commented out, no volumes will be added
|
||||
#
|
||||
# additional_volumes = []
|
||||
|
||||
# Used to change the name of the default AppArmor profile of container engines.
|
||||
#
|
||||
# apparmor_profile = "container-default"
|
||||
|
||||
# Default way to to create a cgroup namespace for the container
|
||||
# Options are:
|
||||
# `private` Create private Cgroup Namespace for the container.
|
||||
# `host` Share host Cgroup Namespace with the container.
|
||||
#
|
||||
# cgroupns = "private"
|
||||
|
||||
# Cgroup management implementation used for the runtime.
|
||||
# Valid options “systemd” or “cgroupfs”
|
||||
#
|
||||
# cgroup_manager = "systemd"
|
||||
|
||||
# List of default capabilities for containers. If it is empty or commented out,
|
||||
# the default capabilities defined in the container engine will be added.
|
||||
#
|
||||
# default_capabilities = [
|
||||
# "AUDIT_WRITE",
|
||||
# "CHOWN",
|
||||
# "DAC_OVERRIDE",
|
||||
# "FOWNER",
|
||||
# "FSETID",
|
||||
# "KILL",
|
||||
# "MKNOD",
|
||||
# "NET_BIND_SERVICE",
|
||||
# "NET_RAW",
|
||||
# "SETGID",
|
||||
# "SETPCAP",
|
||||
# "SETUID",
|
||||
# "SYS_CHROOT",
|
||||
# ]
|
||||
|
||||
# A list of sysctls to be set in containers by default,
|
||||
# specified as "name=value",
|
||||
# for example:"net.ipv4.ping_group_range = 0 1000".
|
||||
#
|
||||
# default_sysctls = [
|
||||
# "net.ipv4.ping_group_range=0 1000",
|
||||
# ]
|
||||
|
||||
# A list of ulimits to be set in containers by default, specified as
|
||||
# "<ulimit name>=<soft limit>:<hard limit>", for example:
|
||||
# "nofile=1024:2048"
|
||||
# See setrlimit(2) for a list of resource names.
|
||||
# Any limit not specified here will be inherited from the process launching the
|
||||
# container engine.
|
||||
# Ulimits has limits for non privileged container engines.
|
||||
#
|
||||
# default_ulimits = [
|
||||
# “nofile”=”1280:2560”,
|
||||
# ]
|
||||
|
||||
# List of default DNS options to be added to /etc/resolv.conf inside of the container.
|
||||
#
|
||||
# dns_options = []
|
||||
|
||||
# List of default DNS search domains to be added to /etc/resolv.conf inside of the container.
|
||||
#
|
||||
# dns_searches = []
|
||||
|
||||
# Set default DNS servers.
|
||||
# This option can be used to override the DNS configuration passed to the
|
||||
# container. The special value “none” can be specified to disable creation of
|
||||
# /etc/resolv.conf in the container.
|
||||
# The /etc/resolv.conf file in the image will be used without changes.
|
||||
#
|
||||
# dns_servers = []
|
||||
|
||||
# Environment variable list for the conmon process; used for passing necessary
|
||||
# environment variables to conmon or the runtime.
|
||||
#
|
||||
# env = [
|
||||
# "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
# ]
|
||||
|
||||
# Pass all host environment variables into the container.
|
||||
#
|
||||
# env_host = false
|
||||
|
||||
# Path to OCI hooks directories for automatically executed hooks.
|
||||
#
|
||||
# hooks_dir = [
|
||||
# “/usr/share/containers/oci/hooks.d”,
|
||||
# ]
|
||||
|
||||
# Default proxy environment variables passed into the container.
|
||||
# The environment variables passed in include:
|
||||
# http_proxy, https_proxy, ftp_proxy, no_proxy, and the upper case versions of
|
||||
# these. This option is needed when host system uses a proxy but container
|
||||
# should not use proxy. Proxy environment variables specified for the container
|
||||
# in any other way will override the values passed from the host.
|
||||
#
|
||||
# http_proxy = true
|
||||
|
||||
# Run an init inside the container that forwards signals and reaps processes.
|
||||
#
|
||||
# init = false
|
||||
|
||||
# Container init binary, if init=true, this is the init binary to be used for containers.
|
||||
#
|
||||
# init_path = "/usr/libexec/podman/catatonit"
|
||||
|
||||
# Default way to to create an IPC namespace (POSIX SysV IPC) for the container
|
||||
# Options are:
|
||||
# `private` Create private IPC Namespace for the container.
|
||||
# `host` Share host IPC Namespace with the container.
|
||||
#
|
||||
# ipcns = "private"
|
||||
|
||||
# container engines use container separation using MAC(SELinux) labeling.
|
||||
# Flag is ignored on label disabled systems.
|
||||
#
|
||||
# label = true
|
||||
|
||||
# Logging driver for the container. Available options: k8s-file and journald.
|
||||
#
|
||||
# log_driver = "k8s-file"
|
||||
|
||||
# Maximum size allowed for the container log file. Negative numbers indicate
|
||||
# that no size limit is imposed. If positive, it must be >= 8192 to match or
|
||||
# exceed conmon's read buffer. The file is truncated and re-opened so the
|
||||
# limit is never exceeded.
|
||||
#
|
||||
# log_size_max = -1
|
||||
|
||||
# Default way to to create a Network namespace for the container
|
||||
# Options are:
|
||||
# `private` Create private Network Namespace for the container.
|
||||
# `host` Share host Network Namespace with the container.
|
||||
# `none` Containers do not use the network
|
||||
#
|
||||
# netns = "private"
|
||||
|
||||
# Create /etc/hosts for the container. By default, container engines manage
|
||||
# /etc/hosts, automatically adding the container's own IP address.
|
||||
#
|
||||
# no_hosts = false
|
||||
|
||||
# Maximum number of processes allowed in a container.
|
||||
#
|
||||
# pids_limit = 2048
|
||||
|
||||
# Default way to to create a PID namespace for the container
|
||||
# Options are:
|
||||
# `private` Create private PID Namespace for the container.
|
||||
# `host` Share host PID Namespace with the container.
|
||||
#
|
||||
# pidns = "private"
|
||||
|
||||
# Path to the seccomp.json profile which is used as the default seccomp profile
|
||||
# for the runtime.
|
||||
#
|
||||
# seccomp_profile = "/usr/share/containers/seccomp.json"
|
||||
|
||||
# Size of /dev/shm. Specified as <number><unit>.
|
||||
# Unit is optional, values:
|
||||
# b (bytes), k (kilobytes), m (megabytes), or g (gigabytes).
|
||||
# If the unit is omitted, the system uses bytes.
|
||||
#
|
||||
# shm_size = "65536k"
|
||||
|
||||
# Default way to to create a UTS namespace for the container
|
||||
# Options are:
|
||||
# `private` Create private UTS Namespace for the container.
|
||||
# `host` Share host UTS Namespace with the container.
|
||||
#
|
||||
# utsns = "private"
|
||||
|
||||
# Default way to to create a User namespace for the container
|
||||
# Options are:
|
||||
# `auto` Create unique User Namespace for the container.
|
||||
# `host` Share host User Namespace with the container.
|
||||
#
|
||||
# userns = "host"
|
||||
|
||||
# Number of UIDs to allocate for the automatic container creation.
|
||||
# UIDs are allocated from the “container” UIDs listed in
|
||||
# /etc/subuid & /etc/subgid
|
||||
#
|
||||
# userns_size=65536
|
||||
|
||||
# The network table contains settings pertaining to the management of
|
||||
# CNI plugins.
|
||||
|
||||
[network]
|
||||
|
||||
# Path to directory where CNI plugin binaries are located.
|
||||
#
|
||||
# cni_plugin_dirs = ["/usr/libexec/cni"]
|
||||
|
||||
# Path to the directory where CNI configuration files are located.
|
||||
#
|
||||
# network_config_dir = "/etc/cni/net.d/"
|
||||
|
||||
[libpod]
|
||||
|
||||
# Environment variables to pass into conmon
|
||||
#
|
||||
# conmon_env_vars = [
|
||||
# "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
# ]
|
||||
|
||||
# Paths to look for the conmon container manager binary
|
||||
#
|
||||
# conmon_path = [
|
||||
# "/usr/libexec/podman/conmon",
|
||||
# "/usr/local/libexec/podman/conmon",
|
||||
# "/usr/local/lib/podman/conmon",
|
||||
# "/usr/bin/conmon",
|
||||
# "/usr/sbin/conmon",
|
||||
# "/usr/local/bin/conmon",
|
||||
# "/usr/local/sbin/conmon"
|
||||
# ]
|
||||
|
||||
# Specify the keys sequence used to detach a container.
|
||||
# Format is a single character [a-Z] or a comma separated sequence of
|
||||
# `ctrl-<value>`, where `<value>` is one of:
|
||||
# `a-z`, `@`, `^`, `[`, `\`, `]`, `^` or `_`
|
||||
#
|
||||
# detach_keys = "ctrl-p,ctrl-q"
|
||||
|
||||
# Determines whether libpod will reserve ports on the host when they are
|
||||
# forwarded to containers. When enabled, when ports are forwarded to containers,
|
||||
# ports are held open by as long as the container is running, ensuring that
|
||||
# they cannot be reused by other programs on the host. However, this can cause
|
||||
# significant memory usage if a container has many ports forwarded to it.
|
||||
# Disabling this can save memory.
|
||||
#
|
||||
# enable_port_reservation = true
|
||||
|
||||
# Selects which logging mechanism to use for container engine events.
|
||||
# Valid values are `journald`, `file` and `none`.
|
||||
#
|
||||
# events_logger = "journald"
|
||||
|
||||
# Default transport method for pulling and pushing for images
|
||||
#
|
||||
# image_default_transport = "docker://"
|
||||
|
||||
# Default command to run the infra container
|
||||
#
|
||||
# infra_command = "/pause"
|
||||
|
||||
# Infra (pause) container image name for pod infra containers. When running a
|
||||
# pod, we start a `pause` process in a container to hold open the namespaces
|
||||
# associated with the pod. This container does nothing other then sleep,
|
||||
# reserving the pods resources for the lifetime of the pod.
|
||||
#
|
||||
# infra_image = "k8s.gcr.io/pause:3.1"
|
||||
|
||||
# Specify the locking mechanism to use; valid values are "shm" and "file".
|
||||
# Change the default only if you are sure of what you are doing, in general
|
||||
# "file" is useful only on platforms where cgo is not available for using the
|
||||
# faster "shm" lock type. You may need to run "podman system renumber" after
|
||||
# you change the lock type.
|
||||
#
|
||||
# lock_type** = "shm"
|
||||
|
||||
# Default libpod namespace
|
||||
# If libpod is joined to a namespace, it will see only containers and pods
|
||||
# that were created in the same namespace, and will create new containers and
|
||||
# pods in that namespace.
|
||||
# The default namespace is "", which corresponds to no namespace. When no
|
||||
# namespace is set, all containers and pods are visible.
|
||||
#
|
||||
# namespace = ""
|
||||
|
||||
# Whether to use chroot instead of pivot_root in the runtime
|
||||
#
|
||||
# no_pivot_root = false
|
||||
|
||||
# Number of locks available for containers and pods.
|
||||
# If this is changed, a lock renumber must be performed (e.g. with the
|
||||
# 'podman system renumber' command).
|
||||
#
|
||||
# num_locks = 2048
|
||||
|
||||
# Directory for persistent libpod files (database, etc)
|
||||
# By default, this will be configured relative to where the containers/storage
|
||||
# stores containers
|
||||
# Uncomment to change location from this default
|
||||
#
|
||||
# static_dir = "/var/lib/containers/storage/libpod"
|
||||
|
||||
# Directory for temporary files. Must be tmpfs (wiped after reboot)
|
||||
#
|
||||
# tmp_dir = "/var/run/libpod"
|
||||
|
||||
# Directory for libpod named volumes.
|
||||
# By default, this will be configured relative to where containers/storage
|
||||
# stores containers.
|
||||
# Uncomment to change location from this default.
|
||||
#
|
||||
# volume_path = "/var/lib/containers/storage/volumes"
|
||||
|
||||
# Default OCI runtime
|
||||
#
|
||||
# runtime = "runc"
|
||||
|
||||
# List of the OCI runtimes that support --format=json. When json is supported
|
||||
# libpod will use it for reporting nicer errors.
|
||||
#
|
||||
# runtime_supports_json = ["crun", "runc"]
|
||||
|
||||
# Paths to look for a valid OCI runtime (runc, runv, etc)
|
||||
[libpod.runtimes]
|
||||
# runc = [
|
||||
# "/usr/bin/runc",
|
||||
# "/usr/sbin/runc",
|
||||
# "/usr/local/bin/runc",
|
||||
# "/usr/local/sbin/runc",
|
||||
# "/sbin/runc",
|
||||
# "/bin/runc",
|
||||
# "/usr/lib/cri-o-runc/sbin/runc",
|
||||
# ]
|
||||
|
||||
# crun = [
|
||||
# "/usr/bin/crun",
|
||||
# "/usr/sbin/crun",
|
||||
# "/usr/local/bin/crun",
|
||||
# "/usr/local/sbin/crun",
|
||||
# "/sbin/crun",
|
||||
# "/bin/crun",
|
||||
# "/run/current-system/sw/bin/crun",
|
||||
# ]
|
||||
|
||||
# The [libpod.runtimes] table MUST be the last entry in this file.
|
||||
# (Unless another table is added)
|
||||
# TOML does not provide a way to end a table other than a further table being
|
||||
# defined, so every key hereafter will be part of [runtimes] and not the main
|
||||
# config.
|
||||
342
vendor/github.com/containers/common/pkg/config/default.go
generated
vendored
Normal file
342
vendor/github.com/containers/common/pkg/config/default.go
generated
vendored
Normal file
@@ -0,0 +1,342 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/containers/common/pkg/cgroups"
|
||||
"github.com/containers/common/pkg/unshare"
|
||||
"github.com/containers/storage"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
// _conmonMinMajorVersion is the major version required for conmon.
|
||||
_conmonMinMajorVersion = 2
|
||||
|
||||
// _conmonMinMinorVersion is the minor version required for conmon.
|
||||
_conmonMinMinorVersion = 0
|
||||
|
||||
// _conmonMinPatchVersion is the sub-minor version required for conmon.
|
||||
_conmonMinPatchVersion = 1
|
||||
|
||||
// _conmonVersionFormatErr is used when the expected versio-format of conmon
|
||||
// has changed.
|
||||
_conmonVersionFormatErr = "conmon version changed format"
|
||||
|
||||
// _defaultGraphRoot points to the default path of the graph root.
|
||||
_defaultGraphRoot = "/var/lib/containers/storage"
|
||||
|
||||
// _defaultTransport is a prefix that we apply to an image name to check
|
||||
// docker hub first for the image.
|
||||
_defaultTransport = "docker://"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultInitPath is the default path to the container-init binary
|
||||
DefaultInitPath = "/usr/libexec/podman/catatonit"
|
||||
// DefaultInfraImage to use for infra container
|
||||
DefaultInfraImage = "k8s.gcr.io/pause:3.1"
|
||||
// DefaultInfraCommand to be run in an infra container
|
||||
DefaultInfraCommand = "/pause"
|
||||
// DefaultRootlessSHMLockPath is the default path for rootless SHM locks
|
||||
DefaultRootlessSHMLockPath = "/libpod_rootless_lock"
|
||||
// DefaultDetachKeys is the default keys sequence for detaching a
|
||||
// container
|
||||
DefaultDetachKeys = "ctrl-p,ctrl-q"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrConmonOutdated indicates the version of conmon found (whether via the configuration or $PATH)
|
||||
// is out of date for the current podman version
|
||||
ErrConmonOutdated = errors.New("outdated conmon version")
|
||||
// ErrInvalidArg indicates that an invalid argument was passed
|
||||
ErrInvalidArg = errors.New("invalid argument")
|
||||
// DefaultHooksDirs defines the default hooks directory
|
||||
DefaultHooksDirs = []string{"/usr/share/containers/oci/hooks.d"}
|
||||
// DefaultCapabilities for the default_capabilities option in the containers.conf file
|
||||
DefaultCapabilities = []string{
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_CHOWN",
|
||||
"CAP_DAC_OVERRIDE",
|
||||
"CAP_FOWNER",
|
||||
"CAP_FSETID",
|
||||
"CAP_KILL",
|
||||
"CAP_MKNOD",
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
"CAP_NET_RAW",
|
||||
"CAP_SETGID",
|
||||
"CAP_SETPCAP",
|
||||
"CAP_SETUID",
|
||||
"CAP_SYS_CHROOT",
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
// EtcDir is the sysconfdir where podman should look for system config files.
|
||||
// It can be overridden at build time.
|
||||
_etcDir = "/etc"
|
||||
// InstallPrefix is the prefix where podman will be installed.
|
||||
// It can be overridden at build time.
|
||||
_installPrefix = "/usr"
|
||||
// CgroupfsCgroupsManager represents cgroupfs native cgroup manager
|
||||
CgroupfsCgroupsManager = "cgroupfs"
|
||||
// DefaultApparmorProfile specifies the default apparmor profile for the container.
|
||||
DefaultApparmorProfile = "container-default"
|
||||
// SystemdCgroupsManager represents systemd native cgroup manager
|
||||
SystemdCgroupsManager = "systemd"
|
||||
// DefaultLogDriver is the default type of log files
|
||||
DefaultLogDriver = "k8s-file"
|
||||
// DefaultLogSizeMax is the default value for the maximum log size
|
||||
// allowed for a container. Negative values mean that no limit is imposed.
|
||||
DefaultLogSizeMax = -1
|
||||
// DefaultPidsLimit is the default value for maximum number of processes
|
||||
// allowed inside a container
|
||||
DefaultPidsLimit = 2048
|
||||
// rootless policy.json file.
|
||||
DefaultRootlessSignaturePolicyPath = ".config/containers/policy.json"
|
||||
// DefaultShmSize default value
|
||||
DefaultShmSize = "65536k"
|
||||
// DefaultUserNSSize default value
|
||||
DefaultUserNSSize = 65536
|
||||
// OCIBufSize limits maximum LogSizeMax
|
||||
OCIBufSize = 8192
|
||||
// SeccompOverridePath if this exists it overrides the default seccomp path.
|
||||
SeccompOverridePath = _etcDir + "/crio/seccomp.json"
|
||||
// SeccompDefaultPath defines the default seccomp path.
|
||||
SeccompDefaultPath = _installPrefix + "/share/containers/seccomp.json"
|
||||
)
|
||||
|
||||
// DefaultConfig defines the default values from containers.conf
|
||||
func DefaultConfig() (*Config, error) {
|
||||
|
||||
defaultLibpodConfig, err := defaultConfigFromMemory()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var signaturePolicyPath string
|
||||
if unshare.IsRootless() {
|
||||
home, err := unshare.HomeDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sigPath := filepath.Join(home, DefaultRootlessSignaturePolicyPath)
|
||||
if _, err := os.Stat(sigPath); err == nil {
|
||||
signaturePolicyPath = sigPath
|
||||
}
|
||||
}
|
||||
|
||||
return &Config{
|
||||
Containers: ContainersConfig{
|
||||
AdditionalDevices: []string{},
|
||||
AdditionalVolumes: []string{},
|
||||
ApparmorProfile: DefaultApparmorProfile,
|
||||
CgroupManager: SystemdCgroupsManager,
|
||||
CgroupNS: "private",
|
||||
DefaultCapabilities: DefaultCapabilities,
|
||||
DefaultSysctls: []string{},
|
||||
DefaultUlimits: []string{},
|
||||
DNSServers: []string{},
|
||||
DNSOptions: []string{},
|
||||
DNSSearches: []string{},
|
||||
EnableLabeling: selinuxEnabled(),
|
||||
Env: []string{
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
},
|
||||
EnvHost: false,
|
||||
HTTPProxy: false,
|
||||
Init: false,
|
||||
InitPath: "",
|
||||
IPCNS: "private",
|
||||
LogDriver: DefaultLogDriver,
|
||||
LogSizeMax: DefaultLogSizeMax,
|
||||
NetNS: "private",
|
||||
NoHosts: false,
|
||||
PidsLimit: DefaultPidsLimit,
|
||||
PidNS: "private",
|
||||
SeccompProfile: SeccompDefaultPath,
|
||||
ShmSize: DefaultShmSize,
|
||||
SignaturePolicyPath: signaturePolicyPath,
|
||||
UTSNS: "private",
|
||||
UserNS: "private",
|
||||
UserNSSize: DefaultUserNSSize,
|
||||
},
|
||||
Network: NetworkConfig{
|
||||
DefaultNetwork: "podman",
|
||||
NetworkConfigDir: cniConfigDir,
|
||||
CNIPluginDirs: cniBinDir,
|
||||
},
|
||||
Libpod: *defaultLibpodConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// defaultConfigFromMemory returns a default libpod configuration. Note that the
|
||||
// config is different for root and rootless. It also parses the storage.conf.
|
||||
func defaultConfigFromMemory() (*LibpodConfig, error) {
|
||||
c := new(LibpodConfig)
|
||||
tmp, err := defaultTmpDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.TmpDir = tmp
|
||||
|
||||
c.EventsLogFilePath = filepath.Join(c.TmpDir, "events", "events.log")
|
||||
|
||||
storeOpts, err := storage.DefaultStoreOptions(unshare.IsRootless(), unshare.GetRootlessUID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if storeOpts.GraphRoot == "" {
|
||||
logrus.Warnf("Storage configuration is unset - using hardcoded default graph root %q", _defaultGraphRoot)
|
||||
storeOpts.GraphRoot = _defaultGraphRoot
|
||||
}
|
||||
c.StaticDir = filepath.Join(storeOpts.GraphRoot, "libpod")
|
||||
c.VolumePath = filepath.Join(storeOpts.GraphRoot, "volumes")
|
||||
c.StorageConfig = storeOpts
|
||||
|
||||
c.HooksDir = DefaultHooksDirs
|
||||
c.ImageDefaultTransport = _defaultTransport
|
||||
c.StateType = BoltDBStateStore
|
||||
|
||||
c.OCIRuntime = "runc"
|
||||
// If we're running on cgroups v2, default to using crun.
|
||||
if onCgroupsv2, _ := cgroups.IsCgroup2UnifiedMode(); onCgroupsv2 {
|
||||
c.OCIRuntime = "crun"
|
||||
}
|
||||
|
||||
c.OCIRuntimes = map[string][]string{
|
||||
"runc": {
|
||||
"/usr/bin/runc",
|
||||
"/usr/sbin/runc",
|
||||
"/usr/local/bin/runc",
|
||||
"/usr/local/sbin/runc",
|
||||
"/sbin/runc",
|
||||
"/bin/runc",
|
||||
"/usr/lib/cri-o-runc/sbin/runc",
|
||||
"/run/current-system/sw/bin/runc",
|
||||
},
|
||||
"crun": {
|
||||
"/usr/bin/crun",
|
||||
"/usr/sbin/crun",
|
||||
"/usr/local/bin/crun",
|
||||
"/usr/local/sbin/crun",
|
||||
"/sbin/crun",
|
||||
"/bin/crun",
|
||||
"/run/current-system/sw/bin/crun",
|
||||
},
|
||||
}
|
||||
c.ConmonEnvVars = []string{
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
}
|
||||
c.ConmonPath = []string{
|
||||
"/usr/libexec/podman/conmon",
|
||||
"/usr/local/libexec/podman/conmon",
|
||||
"/usr/local/lib/podman/conmon",
|
||||
"/usr/bin/conmon",
|
||||
"/usr/sbin/conmon",
|
||||
"/usr/local/bin/conmon",
|
||||
"/usr/local/sbin/conmon",
|
||||
"/run/current-system/sw/bin/conmon",
|
||||
}
|
||||
c.RuntimeSupportsJSON = []string{
|
||||
"crun",
|
||||
"runc",
|
||||
}
|
||||
c.RuntimeSupportsNoCgroups = []string{"crun"}
|
||||
c.InitPath = DefaultInitPath
|
||||
c.NoPivotRoot = false
|
||||
|
||||
c.InfraCommand = DefaultInfraCommand
|
||||
c.InfraImage = DefaultInfraImage
|
||||
c.EnablePortReservation = true
|
||||
c.NumLocks = 2048
|
||||
c.EventsLogger = "journald"
|
||||
c.DetachKeys = DefaultDetachKeys
|
||||
c.SDNotify = false
|
||||
// TODO - ideally we should expose a `type LockType string` along with
|
||||
// constants.
|
||||
c.LockType = "shm"
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func defaultTmpDir() (string, error) {
|
||||
if !unshare.IsRootless() {
|
||||
return "/var/run/libpod", nil
|
||||
}
|
||||
|
||||
runtimeDir, err := getRuntimeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
libpodRuntimeDir := filepath.Join(runtimeDir, "libpod")
|
||||
|
||||
if err := os.Mkdir(libpodRuntimeDir, 0700|os.ModeSticky); err != nil {
|
||||
if !os.IsExist(err) {
|
||||
return "", errors.Wrapf(err, "cannot mkdir %s", libpodRuntimeDir)
|
||||
} else if err := os.Chmod(libpodRuntimeDir, 0700|os.ModeSticky); err != nil {
|
||||
// The directory already exist, just set the sticky bit
|
||||
return "", errors.Wrapf(err, "could not set sticky bit on %s", libpodRuntimeDir)
|
||||
}
|
||||
}
|
||||
return filepath.Join(libpodRuntimeDir, "tmp"), nil
|
||||
}
|
||||
|
||||
// probeConmon calls conmon --version and verifies it is a new enough version for
|
||||
// the runtime expectations podman currently has.
|
||||
func probeConmon(conmonBinary string) error {
|
||||
cmd := exec.Command(conmonBinary, "--version")
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r := regexp.MustCompile(`^conmon version (?P<Major>\d+).(?P<Minor>\d+).(?P<Patch>\d+)`)
|
||||
|
||||
matches := r.FindStringSubmatch(out.String())
|
||||
if len(matches) != 4 {
|
||||
return errors.Wrap(err, _conmonVersionFormatErr)
|
||||
}
|
||||
major, err := strconv.Atoi(matches[1])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, _conmonVersionFormatErr)
|
||||
}
|
||||
if major < _conmonMinMajorVersion {
|
||||
return ErrConmonOutdated
|
||||
}
|
||||
if major > _conmonMinMajorVersion {
|
||||
return nil
|
||||
}
|
||||
|
||||
minor, err := strconv.Atoi(matches[2])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, _conmonVersionFormatErr)
|
||||
}
|
||||
if minor < _conmonMinMinorVersion {
|
||||
return ErrConmonOutdated
|
||||
}
|
||||
if minor > _conmonMinMinorVersion {
|
||||
return nil
|
||||
}
|
||||
|
||||
patch, err := strconv.Atoi(matches[3])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, _conmonVersionFormatErr)
|
||||
}
|
||||
if patch < _conmonMinPatchVersion {
|
||||
return ErrConmonOutdated
|
||||
}
|
||||
if patch > _conmonMinPatchVersion {
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
69
vendor/github.com/containers/common/pkg/config/util_supported.go
generated
vendored
Normal file
69
vendor/github.com/containers/common/pkg/config/util_supported.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// +build linux darwin
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/containers/common/pkg/unshare"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
rootlessRuntimeDirOnce sync.Once
|
||||
rootlessRuntimeDir string
|
||||
)
|
||||
|
||||
// getRuntimeDir returns the runtime directory
|
||||
func getRuntimeDir() (string, error) {
|
||||
var rootlessRuntimeDirError error
|
||||
|
||||
rootlessRuntimeDirOnce.Do(func() {
|
||||
runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
|
||||
uid := fmt.Sprintf("%d", unshare.GetRootlessUID())
|
||||
if runtimeDir == "" {
|
||||
tmpDir := filepath.Join("/run", "user", uid)
|
||||
if err := os.MkdirAll(tmpDir, 0700); err != nil {
|
||||
logrus.Debugf("unable to make temp dir %s", tmpDir)
|
||||
}
|
||||
st, err := os.Stat(tmpDir)
|
||||
if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 {
|
||||
runtimeDir = tmpDir
|
||||
}
|
||||
}
|
||||
if runtimeDir == "" {
|
||||
tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("run-%s", uid))
|
||||
if err := os.MkdirAll(tmpDir, 0700); err != nil {
|
||||
logrus.Debugf("unable to make temp dir %s", tmpDir)
|
||||
}
|
||||
st, err := os.Stat(tmpDir)
|
||||
if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 {
|
||||
runtimeDir = tmpDir
|
||||
}
|
||||
}
|
||||
if runtimeDir == "" {
|
||||
home := os.Getenv("HOME")
|
||||
if home == "" {
|
||||
rootlessRuntimeDirError = fmt.Errorf("neither XDG_RUNTIME_DIR nor HOME was set non-empty")
|
||||
return
|
||||
}
|
||||
resolvedHome, err := filepath.EvalSymlinks(home)
|
||||
if err != nil {
|
||||
rootlessRuntimeDirError = errors.Wrapf(err, "cannot resolve %s", home)
|
||||
return
|
||||
}
|
||||
runtimeDir = filepath.Join(resolvedHome, "rundir")
|
||||
}
|
||||
rootlessRuntimeDir = runtimeDir
|
||||
})
|
||||
|
||||
if rootlessRuntimeDirError != nil {
|
||||
return "", rootlessRuntimeDirError
|
||||
}
|
||||
return rootlessRuntimeDir, nil
|
||||
}
|
||||
12
vendor/github.com/containers/common/pkg/config/util_windows.go
generated
vendored
Normal file
12
vendor/github.com/containers/common/pkg/config/util_windows.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
// +build windows
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// getRuntimeDir returns the runtime directory
|
||||
func getRuntimeDir() (string, error) {
|
||||
return "", errors.New("this function is not implemented for windows")
|
||||
}
|
||||
169
vendor/github.com/docker/docker/oci/caps/utils.go
generated
vendored
Normal file
169
vendor/github.com/docker/docker/oci/caps/utils.go
generated
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
package caps // import "github.com/docker/docker/oci/caps"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/syndtr/gocapability/capability"
|
||||
)
|
||||
|
||||
var capabilityList Capabilities
|
||||
|
||||
func init() {
|
||||
last := capability.CAP_LAST_CAP
|
||||
// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
|
||||
if last == capability.Cap(63) {
|
||||
last = capability.CAP_BLOCK_SUSPEND
|
||||
}
|
||||
for _, cap := range capability.List() {
|
||||
if cap > last {
|
||||
continue
|
||||
}
|
||||
capabilityList = append(capabilityList,
|
||||
&CapabilityMapping{
|
||||
Key: "CAP_" + strings.ToUpper(cap.String()),
|
||||
Value: cap,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
// CapabilityMapping maps linux capability name to its value of capability.Cap type
|
||||
// Capabilities is one of the security systems in Linux Security Module (LSM)
|
||||
// framework provided by the kernel.
|
||||
// For more details on capabilities, see http://man7.org/linux/man-pages/man7/capabilities.7.html
|
||||
CapabilityMapping struct {
|
||||
Key string `json:"key,omitempty"`
|
||||
Value capability.Cap `json:"value,omitempty"`
|
||||
}
|
||||
// Capabilities contains all CapabilityMapping
|
||||
Capabilities []*CapabilityMapping
|
||||
)
|
||||
|
||||
// String returns <key> of CapabilityMapping
|
||||
func (c *CapabilityMapping) String() string {
|
||||
return c.Key
|
||||
}
|
||||
|
||||
// GetCapability returns CapabilityMapping which contains specific key
|
||||
func GetCapability(key string) *CapabilityMapping {
|
||||
for _, capp := range capabilityList {
|
||||
if capp.Key == key {
|
||||
cpy := *capp
|
||||
return &cpy
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAllCapabilities returns all of the capabilities
|
||||
func GetAllCapabilities() []string {
|
||||
output := make([]string, len(capabilityList))
|
||||
for i, capability := range capabilityList {
|
||||
output[i] = capability.String()
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
// inSlice tests whether a string is contained in a slice of strings or not.
|
||||
func inSlice(slice []string, s string) bool {
|
||||
for _, ss := range slice {
|
||||
if s == ss {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const allCapabilities = "ALL"
|
||||
|
||||
// NormalizeLegacyCapabilities normalizes, and validates CapAdd/CapDrop capabilities
|
||||
// by upper-casing them, and adding a CAP_ prefix (if not yet present).
|
||||
//
|
||||
// This function also accepts the "ALL" magic-value, that's used by CapAdd/CapDrop.
|
||||
func NormalizeLegacyCapabilities(caps []string) ([]string, error) {
|
||||
var normalized []string
|
||||
|
||||
valids := GetAllCapabilities()
|
||||
for _, c := range caps {
|
||||
c = strings.ToUpper(c)
|
||||
if c == allCapabilities {
|
||||
normalized = append(normalized, c)
|
||||
continue
|
||||
}
|
||||
if !strings.HasPrefix(c, "CAP_") {
|
||||
c = "CAP_" + c
|
||||
}
|
||||
if !inSlice(valids, c) {
|
||||
return nil, errdefs.InvalidParameter(fmt.Errorf("unknown capability: %q", c))
|
||||
}
|
||||
normalized = append(normalized, c)
|
||||
}
|
||||
return normalized, nil
|
||||
}
|
||||
|
||||
// ValidateCapabilities validates if caps only contains valid capabilities
|
||||
func ValidateCapabilities(caps []string) error {
|
||||
valids := GetAllCapabilities()
|
||||
for _, c := range caps {
|
||||
if !inSlice(valids, c) {
|
||||
return errdefs.InvalidParameter(fmt.Errorf("unknown capability: %q", c))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TweakCapabilities tweaks capabilities by adding, dropping, or overriding
|
||||
// capabilities in the basics capabilities list.
|
||||
func TweakCapabilities(basics, adds, drops, capabilities []string, privileged bool) ([]string, error) {
|
||||
switch {
|
||||
case privileged:
|
||||
// Privileged containers get all capabilities
|
||||
return GetAllCapabilities(), nil
|
||||
case capabilities != nil:
|
||||
// Use custom set of capabilities
|
||||
if err := ValidateCapabilities(capabilities); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return capabilities, nil
|
||||
case len(adds) == 0 && len(drops) == 0:
|
||||
// Nothing to tweak; we're done
|
||||
return basics, nil
|
||||
}
|
||||
|
||||
capDrop, err := NormalizeLegacyCapabilities(drops)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
capAdd, err := NormalizeLegacyCapabilities(adds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var caps []string
|
||||
|
||||
switch {
|
||||
case inSlice(capAdd, allCapabilities):
|
||||
// Add all capabilities except ones on capDrop
|
||||
for _, c := range GetAllCapabilities() {
|
||||
if !inSlice(capDrop, c) {
|
||||
caps = append(caps, c)
|
||||
}
|
||||
}
|
||||
case inSlice(capDrop, allCapabilities):
|
||||
// "Drop" all capabilities; use what's in capAdd instead
|
||||
caps = capAdd
|
||||
default:
|
||||
// First drop some capabilities
|
||||
for _, c := range basics {
|
||||
if !inSlice(capDrop, c) {
|
||||
caps = append(caps, c)
|
||||
}
|
||||
}
|
||||
// Then add the list of capabilities from capAdd
|
||||
caps = append(caps, capAdd...)
|
||||
}
|
||||
return caps, nil
|
||||
}
|
||||
5
vendor/modules.txt
vendored
5
vendor/modules.txt
vendored
@@ -48,8 +48,10 @@ github.com/containernetworking/cni/pkg/types
|
||||
github.com/containernetworking/cni/pkg/types/020
|
||||
github.com/containernetworking/cni/pkg/types/current
|
||||
github.com/containernetworking/cni/pkg/version
|
||||
# github.com/containers/common v0.0.7
|
||||
# github.com/containers/common v0.0.8-0.20200108114752-d87ce6ce296b
|
||||
github.com/containers/common/pkg/caps
|
||||
github.com/containers/common/pkg/cgroups
|
||||
github.com/containers/common/pkg/config
|
||||
github.com/containers/common/pkg/unshare
|
||||
# github.com/containers/image/v5 v5.1.0
|
||||
github.com/containers/image/v5/copy
|
||||
@@ -178,6 +180,7 @@ github.com/docker/docker/api/types/versions
|
||||
github.com/docker/docker/api/types/volume
|
||||
github.com/docker/docker/client
|
||||
github.com/docker/docker/errdefs
|
||||
github.com/docker/docker/oci/caps
|
||||
github.com/docker/docker/pkg/archive
|
||||
github.com/docker/docker/pkg/fileutils
|
||||
github.com/docker/docker/pkg/homedir
|
||||
|
||||
Reference in New Issue
Block a user