Merge pull request #14341 from vrothberg/todo-part-1

TODO's and FIXME's [PART 1]
This commit is contained in:
OpenShift Merge Robot
2022-05-24 12:50:59 -04:00
committed by GitHub
47 changed files with 393 additions and 239 deletions

View File

@ -8,6 +8,7 @@ import (
"strconv" "strconv"
"strings" "strings"
libimageDefine "github.com/containers/common/libimage/define"
"github.com/containers/common/libnetwork/types" "github.com/containers/common/libnetwork/types"
"github.com/containers/common/pkg/config" "github.com/containers/common/pkg/config"
"github.com/containers/image/v5/pkg/sysregistriesv2" "github.com/containers/image/v5/pkg/sysregistriesv2"
@ -496,6 +497,11 @@ func AutocompleteImages(cmd *cobra.Command, args []string, toComplete string) ([
return getImages(cmd, toComplete) return getImages(cmd, toComplete)
} }
// AutocompleteImageSearchFilters - Autocomplate `search --filter`.
func AutocompleteImageSearchFilters(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return libimageDefine.SearchFilters, cobra.ShellCompDirectiveNoFileComp
}
// AutocompletePodExitPolicy - Autocomplete pod exit policy. // AutocompletePodExitPolicy - Autocomplete pod exit policy.
func AutocompletePodExitPolicy(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { func AutocompletePodExitPolicy(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return config.PodExitPolicies, cobra.ShellCompDirectiveNoFileComp return config.PodExitPolicies, cobra.ShellCompDirectiveNoFileComp

View File

@ -7,7 +7,6 @@ import (
"github.com/containers/common/pkg/report" "github.com/containers/common/pkg/report"
"github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/common"
"github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/cmd/podman/utils"
"github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/entities"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -71,16 +70,12 @@ func mount(cmd *cobra.Command, args []string) error {
return err return err
} }
if len(args) > 0 || mountOpts.All { if len(args) == 1 && mountOpts.Format == "" && !mountOpts.All {
var errs utils.OutputErrors if len(reports) != 1 {
for _, r := range reports { return fmt.Errorf("internal error: expected 1 report but got %d", len(reports))
if r.Err == nil {
fmt.Println(r.Path)
continue
}
errs = append(errs, r.Err)
} }
return errs.PrintErrors() fmt.Println(reports[0].Path)
return nil
} }
switch { switch {

View File

@ -83,8 +83,7 @@ func searchFlags(cmd *cobra.Command) {
filterFlagName := "filter" filterFlagName := "filter"
flags.StringSliceVarP(&searchOptions.Filters, filterFlagName, "f", []string{}, "Filter output based on conditions provided (default [])") flags.StringSliceVarP(&searchOptions.Filters, filterFlagName, "f", []string{}, "Filter output based on conditions provided (default [])")
// TODO add custom filter function _ = cmd.RegisterFlagCompletionFunc(filterFlagName, common.AutocompleteImageSearchFilters)
_ = cmd.RegisterFlagCompletionFunc(filterFlagName, completion.AutocompleteNone)
formatFlagName := "format" formatFlagName := "format"
flags.StringVar(&searchOptions.Format, formatFlagName, "", "Change the output format to JSON or a Go template") flags.StringVar(&searchOptions.Format, formatFlagName, "", "Change the output format to JSON or a Go template")

2
go.mod
View File

@ -12,7 +12,7 @@ require (
github.com/containernetworking/cni v1.1.0 github.com/containernetworking/cni v1.1.0
github.com/containernetworking/plugins v1.1.1 github.com/containernetworking/plugins v1.1.1
github.com/containers/buildah v1.26.1 github.com/containers/buildah v1.26.1
github.com/containers/common v0.48.1-0.20220512112240-7536bf6ff9b1 github.com/containers/common v0.48.1-0.20220523155016-2fd37da97824
github.com/containers/conmon v2.0.20+incompatible github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.21.2-0.20220519193817-1e26896b8059 github.com/containers/image/v5 v5.21.2-0.20220519193817-1e26896b8059
github.com/containers/ocicrypt v1.1.4-0.20220428134531-566b808bdf6f github.com/containers/ocicrypt v1.1.4-0.20220428134531-566b808bdf6f

5
go.sum
View File

@ -340,11 +340,12 @@ github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19
github.com/containers/buildah v1.26.1 h1:D65Vuo+orsI14WWtJhSX6KrpgBBa7+hveVWevzG8p8E= github.com/containers/buildah v1.26.1 h1:D65Vuo+orsI14WWtJhSX6KrpgBBa7+hveVWevzG8p8E=
github.com/containers/buildah v1.26.1/go.mod h1:CsWSG8OpJd8v3mlLREJzVAOBgC93DjRNALUVHoi8QsY= github.com/containers/buildah v1.26.1/go.mod h1:CsWSG8OpJd8v3mlLREJzVAOBgC93DjRNALUVHoi8QsY=
github.com/containers/common v0.48.0/go.mod h1:zPLZCfLXfnd1jI0QRsD4By54fP4k1+ifQs+tulIe3o0= github.com/containers/common v0.48.0/go.mod h1:zPLZCfLXfnd1jI0QRsD4By54fP4k1+ifQs+tulIe3o0=
github.com/containers/common v0.48.1-0.20220512112240-7536bf6ff9b1 h1:U+2rYjzRCvI3WRSFf+Rohtu7jRgk/VhJjjFHbU6j0Sk= github.com/containers/common v0.48.1-0.20220523155016-2fd37da97824 h1:5gMIUUpIK9DvHrrlj1Tik8GfCh5DEuVqm0JnYHWYUDw=
github.com/containers/common v0.48.1-0.20220512112240-7536bf6ff9b1/go.mod h1:h8YZVXePE7UViJQ3fPWpYAaeDNYBCzGtL5dA3N8yfT8= github.com/containers/common v0.48.1-0.20220523155016-2fd37da97824/go.mod h1:Ru/JjL1CTHzlxghVMhchzcFUwHLvlIeR5/SUMw8VUOI=
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.21.1/go.mod h1:zl35egpcDQa79IEXIuoUe1bW+D1pdxRxYjNlyb3YiXw= github.com/containers/image/v5 v5.21.1/go.mod h1:zl35egpcDQa79IEXIuoUe1bW+D1pdxRxYjNlyb3YiXw=
github.com/containers/image/v5 v5.21.2-0.20220511203756-fe4fd4ed8be4/go.mod h1:OsX9sFexyGF0FCNAjfcVFv3IwMqDyLyV/WQY/roLPcE=
github.com/containers/image/v5 v5.21.2-0.20220519193817-1e26896b8059 h1:/FzsjrQ2nJtMom9IXEGieORlwUk/NyDuuz5SWcNo324= github.com/containers/image/v5 v5.21.2-0.20220519193817-1e26896b8059 h1:/FzsjrQ2nJtMom9IXEGieORlwUk/NyDuuz5SWcNo324=
github.com/containers/image/v5 v5.21.2-0.20220519193817-1e26896b8059/go.mod h1:KntCBNQn3qOuZmQuJ38ORyTozmWXiuo05Vef2S0Sm5M= github.com/containers/image/v5 v5.21.2-0.20220519193817-1e26896b8059/go.mod h1:KntCBNQn3qOuZmQuJ38ORyTozmWXiuo05Vef2S0Sm5M=
github.com/containers/libtrust v0.0.0-20200511145503-9c3a6c22cd9a h1:spAGlqziZjCJL25C6F1zsQY05tfCKE9F5YwtEWWe6hU= github.com/containers/libtrust v0.0.0-20200511145503-9c3a6c22cd9a h1:spAGlqziZjCJL25C6F1zsQY05tfCKE9F5YwtEWWe6hU=

View File

@ -96,7 +96,7 @@ func (c *Container) Top(descriptors []string) ([]string, error) {
// For more details, please refer to github.com/containers/psgo. // For more details, please refer to github.com/containers/psgo.
func (c *Container) GetContainerPidInformation(descriptors []string) ([]string, error) { func (c *Container) GetContainerPidInformation(descriptors []string) ([]string, error) {
pid := strconv.Itoa(c.state.PID) pid := strconv.Itoa(c.state.PID)
// TODO: psgo returns a [][]string to give users the ability to apply // NOTE: psgo returns a [][]string to give users the ability to apply
// filters on the data. We need to change the API here // filters on the data. We need to change the API here
// to return a [][]string if we want to make use of // to return a [][]string if we want to make use of
// filtering. // filtering.

View File

@ -280,7 +280,6 @@ func Push(ctx context.Context, source string, destination string, options *PushO
if err != nil { if err != nil {
return err return err
} }
// TODO: have a global system context we can pass around (1st argument)
header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword()) header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword())
if err != nil { if err != nil {
return err return err
@ -329,7 +328,6 @@ func Search(ctx context.Context, term string, options *SearchOptions) ([]entitie
params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify())) params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify()))
} }
// TODO: have a global system context we can pass around (1st argument)
header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, "", "") header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, "", "")
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -42,7 +42,6 @@ func Pull(ctx context.Context, rawImage string, options *PullOptions) ([]string,
params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify())) params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify()))
} }
// TODO: have a global system context we can pass around (1st argument)
header, err := auth.MakeXRegistryAuthHeader(&types.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword()) header, err := auth.MakeXRegistryAuthHeader(&types.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword())
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -16,9 +16,6 @@ func Remove(ctx context.Context, images []string, options *RemoveOptions) (*enti
if options == nil { if options == nil {
options = new(RemoveOptions) options = new(RemoveOptions)
} }
// FIXME - bindings tests are missing for this endpoint. Once the CI is
// re-enabled for bindings, we need to add them. At the time of writing,
// the tests don't compile.
var report types.LibpodImagesRemoveReport var report types.LibpodImagesRemoveReport
conn, err := bindings.GetClient(ctx) conn, err := bindings.GetClient(ctx)
if err != nil { if err != nil {

View File

@ -66,10 +66,9 @@ type ImageSummary struct {
Dangling bool `json:",omitempty"` Dangling bool `json:",omitempty"`
// Podman extensions // Podman extensions
Names []string `json:",omitempty"` Names []string `json:",omitempty"`
Digest string `json:",omitempty"` Digest string `json:",omitempty"`
ConfigDigest string `json:",omitempty"` History []string `json:",omitempty"`
History []string `json:",omitempty"`
} }
func (i *ImageSummary) Id() string { // nolint func (i *ImageSummary) Id() string { // nolint
@ -398,7 +397,6 @@ type ImageUnmountOptions struct {
// ImageMountReport describes the response from image mount // ImageMountReport describes the response from image mount
type ImageMountReport struct { type ImageMountReport struct {
Err error
Id string // nolint Id string // nolint
Name string Name string
Repositories []string Repositories []string

View File

@ -159,10 +159,6 @@ func (ir *ImageEngine) Mount(ctx context.Context, nameOrIDs []string, opts entit
mountReports := []*entities.ImageMountReport{} mountReports := []*entities.ImageMountReport{}
listMountsOnly := !opts.All && len(nameOrIDs) == 0 listMountsOnly := !opts.All && len(nameOrIDs) == 0
for _, i := range images { for _, i := range images {
// TODO: the .Err fields are not used. This pre-dates the
// libimage migration but should be addressed at some point.
// A quick glimpse at cmd/podman/image/mount.go suggests that
// the errors needed to be handled there as well.
var mountPoint string var mountPoint string
var err error var err error
if listMountsOnly { if listMountsOnly {

View File

@ -36,9 +36,7 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions)
} }
e := entities.ImageSummary{ e := entities.ImageSummary{
ID: img.ID(), ID: img.ID(),
// TODO: libpod/image didn't set it but libimage should
// ConfigDigest: string(img.ConfigDigest),
Created: img.Created().Unix(), Created: img.Created().Unix(),
Dangling: isDangling, Dangling: isDangling,
Digest: string(img.Digest()), Digest: string(img.Digest()),

View File

@ -16,39 +16,3 @@ func TestToDomainHistoryLayer(t *testing.T) {
newLayer := toDomainHistoryLayer(&layer) newLayer := toDomainHistoryLayer(&layer)
assert.Equal(t, layer.Size, newLayer.Size) assert.Equal(t, layer.Size, newLayer.Size)
} }
//
// import (
// "context"
// "testing"
//
// "github.com/stretchr/testify/mock"
// )
//
// type MockImageRuntime struct {
// mock.Mock
// }
//
// func (m *MockImageRuntime) Delete(ctx context.Context, renderer func() interface{}, name string) error {
// _ = m.Called(ctx, renderer, name)
// return nil
// }
//
// func TestImageSuccess(t *testing.T) {
// actual := func() interface{} { return nil }
//
// m := new(MockImageRuntime)
// m.On(
// "Delete",
// mock.AnythingOfType("*context.emptyCtx"),
// mock.AnythingOfType("func() interface {}"),
// "fedora").
// Return(nil)
//
// r := DirectImageRuntime{m}
// err := r.Delete(context.TODO(), actual, "fedora")
// if err != nil {
// t.Errorf("should be nil, got: %v", err)
// }
// m.AssertExpectations(t)
// }

View File

@ -41,18 +41,3 @@ type RootFS struct {
Type string `json:"Type"` Type string `json:"Type"`
Layers []digest.Digest `json:"Layers"` Layers []digest.Digest `json:"Layers"`
} }
// ImageResult is used for podman images for collection and output.
type ImageResult struct {
Tag string
Repository string
RepoDigests []string
RepoTags []string
ID string
Digest digest.Digest
ConfigDigest digest.Digest
Created time.Time
Size *uint64
Labels map[string]string
Dangling bool
}

View File

@ -455,7 +455,6 @@ registries = ['{{.Host}}:{{.Port}}']`
}) })
It("podman search with wildcards", func() { It("podman search with wildcards", func() {
Skip("FIXME: search on registry.redhat.io is broken (Dec 16 '21)")
search := podmanTest.Podman([]string{"search", "registry.redhat.io/*openshift*"}) search := podmanTest.Podman([]string{"search", "registry.redhat.io/*openshift*"})
search.WaitWithDefaultTimeout() search.WaitWithDefaultTimeout()
Expect(search).Should(Exit(0)) Expect(search).Should(Exit(0))

View File

@ -50,6 +50,10 @@ load helpers
run_podman image mount $IMAGE run_podman image mount $IMAGE
mount_path="$output" mount_path="$output"
# Make sure that `mount -a` prints a table
run_podman image mount -a
is "$output" "$IMAGE .*$mount_path"
test -d $mount_path test -d $mount_path
# Image is custom-built and has a file containing the YMD tag. Check it. # Image is custom-built and has a file containing the YMD tag. Check it.
@ -62,8 +66,8 @@ load helpers
run_podman image mount run_podman image mount
is "$output" "$IMAGE *$mount_path" "podman image mount with no args" is "$output" "$IMAGE *$mount_path" "podman image mount with no args"
# Clean up # Clean up: -f since we mounted it twice
run_podman image umount $IMAGE run_podman image umount -f $IMAGE
is "$output" "$iid" "podman image umount: image ID of what was umounted" is "$output" "$iid" "podman image umount: image ID of what was umounted"
run_podman image umount $IMAGE run_podman image umount $IMAGE

View File

@ -0,0 +1,13 @@
package define
const (
// SearchFilterAutomated is the key for filtering images by their automated attribute.
SearchFilterAutomated = "is-automated"
// SearchFilterOfficial is the key for filtering images by their official attribute.
SearchFilterOfficial = "is-official"
// SearchFilterStars is the key for filtering images by stars.
SearchFilterStars = "stars"
)
// SearchFilters includes all supported search filters.
var SearchFilters = []string{SearchFilterAutomated, SearchFilterOfficial, SearchFilterStars}

View File

@ -114,6 +114,11 @@ func (r *Runtime) loadMultiImageDockerArchive(ctx context.Context, ref types.Ima
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer func() {
if err := reader.Close(); err != nil {
logrus.Errorf("Closing reader of docker archive: %v", err)
}
}()
refLists, err := reader.List() refLists, err := reader.List()
if err != nil { if err != nil {

View File

@ -315,6 +315,11 @@ func (r *Runtime) copyFromDockerArchive(ctx context.Context, ref types.ImageRefe
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer func() {
if err := reader.Close(); err != nil {
logrus.Errorf("Closing reader of docker archive: %v", err)
}
}()
return r.copyFromDockerArchiveReaderReference(ctx, reader, readerRef, options) return r.copyFromDockerArchiveReaderReference(ctx, reader, readerRef, options)
} }

View File

@ -7,6 +7,7 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/containers/common/libimage/define"
registryTransport "github.com/containers/image/v5/docker" registryTransport "github.com/containers/image/v5/docker"
"github.com/containers/image/v5/pkg/sysregistriesv2" "github.com/containers/image/v5/pkg/sysregistriesv2"
"github.com/containers/image/v5/transports/alltransports" "github.com/containers/image/v5/transports/alltransports"
@ -81,22 +82,22 @@ func ParseSearchFilter(filter []string) (*SearchFilter, error) {
for _, f := range filter { for _, f := range filter {
arr := strings.SplitN(f, "=", 2) arr := strings.SplitN(f, "=", 2)
switch arr[0] { switch arr[0] {
case "stars": case define.SearchFilterStars:
if len(arr) < 2 { if len(arr) < 2 {
return nil, errors.Errorf("invalid `stars` filter %q, should be stars=<value>", filter) return nil, errors.Errorf("invalid filter %q, should be stars=<value>", filter)
} }
stars, err := strconv.Atoi(arr[1]) stars, err := strconv.Atoi(arr[1])
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "incorrect value type for stars filter") return nil, errors.Wrapf(err, "incorrect value type for stars filter")
} }
sFilter.Stars = stars sFilter.Stars = stars
case "is-automated": case define.SearchFilterAutomated:
if len(arr) == 2 && arr[1] == "false" { if len(arr) == 2 && arr[1] == "false" {
sFilter.IsAutomated = types.OptionalBoolFalse sFilter.IsAutomated = types.OptionalBoolFalse
} else { } else {
sFilter.IsAutomated = types.OptionalBoolTrue sFilter.IsAutomated = types.OptionalBoolTrue
} }
case "is-official": case define.SearchFilterOfficial:
if len(arr) == 2 && arr[1] == "false" { if len(arr) == 2 && arr[1] == "false" {
sFilter.IsOfficial = types.OptionalBoolFalse sFilter.IsOfficial = types.OptionalBoolFalse
} else { } else {

View File

@ -1,5 +1,5 @@
//go:build linux //go:build linux || freebsd
// +build linux // +build linux freebsd
package cni package cni

View File

@ -16,8 +16,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
//go:build linux //go:build linux || freebsd
// +build linux // +build linux freebsd
package cni package cni

View File

@ -1,5 +1,5 @@
//go:build linux //go:build linux || freebsd
// +build linux // +build linux freebsd
package cni package cni

View File

@ -1,5 +1,5 @@
//go:build linux //go:build linux || freebsd
// +build linux // +build linux freebsd
package cni package cni
@ -12,7 +12,6 @@ import (
pkgutil "github.com/containers/common/pkg/util" pkgutil "github.com/containers/common/pkg/util"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
) )
// NetworkCreate will take a partial filled Network and fill the // NetworkCreate will take a partial filled Network and fill the
@ -133,14 +132,7 @@ func (n *cniNetwork) NetworkRemove(nameOrID string) error {
// Remove the bridge network interface on the host. // Remove the bridge network interface on the host.
if network.libpodNet.Driver == types.BridgeNetworkDriver { if network.libpodNet.Driver == types.BridgeNetworkDriver {
link, err := netlink.LinkByName(network.libpodNet.NetworkInterface) deleteLink(network.libpodNet.NetworkInterface)
if err == nil {
err = netlink.LinkDel(link)
// only log the error, it is not fatal
if err != nil {
logrus.Infof("Failed to remove network interface %s: %v", network.libpodNet.NetworkInterface, err)
}
}
} }
file := network.filename file := network.filename

View File

@ -0,0 +1,17 @@
//go:build freebsd
// +build freebsd
package cni
import (
"os/exec"
"github.com/sirupsen/logrus"
)
func deleteLink(name string) {
if output, err := exec.Command("ifconfig", name, "destroy").CombinedOutput(); err != nil {
// only log the error, it is not fatal
logrus.Infof("Failed to remove network interface %s: %v: %s", name, err, output)
}
}

View File

@ -0,0 +1,20 @@
//go:build linux
// +build linux
package cni
import (
"github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
)
func deleteLink(name string) {
link, err := netlink.LinkByName(name)
if err == nil {
err = netlink.LinkDel(link)
// only log the error, it is not fatal
if err != nil {
logrus.Infof("Failed to remove network interface %s: %v", name, err)
}
}
}

View File

@ -1,5 +1,5 @@
//go:build linux //go:build linux || freebsd
// +build linux // +build linux freebsd
package cni package cni

View File

@ -1,5 +1,5 @@
//go:build linux //go:build linux || freebsd
// +build linux // +build linux freebsd
package cni package cni
@ -12,13 +12,11 @@ import (
"github.com/containernetworking/cni/libcni" "github.com/containernetworking/cni/libcni"
cnitypes "github.com/containernetworking/cni/pkg/types" cnitypes "github.com/containernetworking/cni/pkg/types"
types040 "github.com/containernetworking/cni/pkg/types/040" types040 "github.com/containernetworking/cni/pkg/types/040"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containers/common/libnetwork/internal/util" "github.com/containers/common/libnetwork/internal/util"
"github.com/containers/common/libnetwork/types" "github.com/containers/common/libnetwork/types"
"github.com/hashicorp/go-multierror" "github.com/hashicorp/go-multierror"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
) )
// Setup will setup the container network namespace. It returns // Setup will setup the container network namespace. It returns
@ -36,14 +34,7 @@ func (n *cniNetwork) Setup(namespacePath string, options types.SetupOptions) (ma
return nil, err return nil, err
} }
// set the loopback adapter up in the container netns err = setupLoopback(namespacePath)
err = ns.WithNetNSPath(namespacePath, func(_ ns.NetNS) error {
link, err := netlink.LinkByName("lo")
if err == nil {
err = netlink.LinkSetUp(link)
}
return err
})
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "failed to set the loopback adapter up") return nil, errors.Wrapf(err, "failed to set the loopback adapter up")
} }

View File

@ -0,0 +1,13 @@
package cni
import (
"os/exec"
)
// FreeBSD vnet adds the lo0 interface automatically - we just need to
// add the default address. Note: this will also add ::1 as a side
// effect.
func setupLoopback(namespacePath string) error {
// The jexec wrapper runs the ifconfig command inside the jail.
return exec.Command("jexec", namespacePath, "ifconfig", "lo0", "inet", "127.0.0.1").Run()
}

View File

@ -0,0 +1,17 @@
package cni
import (
"github.com/containernetworking/plugins/pkg/ns"
"github.com/vishvananda/netlink"
)
func setupLoopback(namespacePath string) error {
// set the loopback adapter up in the container netns
return ns.WithNetNSPath(namespacePath, func(_ ns.NetNS) error {
link, err := netlink.LinkByName("lo")
if err == nil {
err = netlink.LinkSetUp(link)
}
return err
})
}

View File

@ -1,5 +1,5 @@
//go:build linux //go:build linux || freebsd
// +build linux // +build linux freebsd
package netavark package netavark

View File

@ -1,5 +1,5 @@
//go:build linux //go:build linux || freebsd
// +build linux // +build linux freebsd
package netavark package netavark

View File

@ -1,5 +1,5 @@
//go:build linux //go:build linux || freebsd
// +build linux // +build linux freebsd
package netavark package netavark

View File

@ -1,5 +1,5 @@
//go:build linux //go:build linux || freebsd
// +build linux // +build linux freebsd
package netavark package netavark

View File

@ -1,5 +1,5 @@
//go:build linux //go:build linux || freebsd
// +build linux // +build linux freebsd
package netavark package netavark

View File

@ -1,5 +1,5 @@
//go:build linux //go:build linux || freebsd
// +build linux // +build linux freebsd
package netavark package netavark

View File

@ -1,5 +1,5 @@
//go:build linux //go:build linux || freebsd
// +build linux // +build linux freebsd
package network package network
@ -25,14 +25,8 @@ import (
const ( const (
// defaultNetworkBackendFileName is the file name for sentinel file to store the backend // defaultNetworkBackendFileName is the file name for sentinel file to store the backend
defaultNetworkBackendFileName = "defaultNetworkBackend" defaultNetworkBackendFileName = "defaultNetworkBackend"
// cniConfigDir is the directory where cni configuration is found
cniConfigDir = "/etc/cni/net.d/"
// cniConfigDirRootless is the directory in XDG_CONFIG_HOME for cni plugins // cniConfigDirRootless is the directory in XDG_CONFIG_HOME for cni plugins
cniConfigDirRootless = "cni/net.d/" cniConfigDirRootless = "cni/net.d/"
// netavarkConfigDir is the config directory for the rootful network files
netavarkConfigDir = "/etc/containers/networks"
// netavarkRunDir is the run directory for the rootful temporary network files such as the ipam db
netavarkRunDir = "/run/containers/networks"
// netavarkBinary is the name of the netavark binary // netavarkBinary is the name of the netavark binary
netavarkBinary = "netavark" netavarkBinary = "netavark"

View File

@ -0,0 +1,10 @@
package network
const (
// cniConfigDir is the directory where cni configuration is found
cniConfigDir = "/usr/local/etc/cni/net.d/"
// netavarkConfigDir is the config directory for the rootful network files
netavarkConfigDir = "/usr/local/etc/containers/networks"
// netavarkRunDir is the run directory for the rootful temporary network files such as the ipam db
netavarkRunDir = "/var/run/containers/networks"
)

View File

@ -0,0 +1,10 @@
package network
const (
// cniConfigDir is the directory where cni configuration is found
cniConfigDir = "/etc/cni/net.d/"
// netavarkConfigDir is the config directory for the rootful network files
netavarkConfigDir = "/etc/containers/networks"
// netavarkRunDir is the run directory for the rootful temporary network files such as the ipam db
netavarkRunDir = "/run/containers/networks"
)

View File

@ -99,7 +99,7 @@ func UserOwnsCurrentSystemdCgroup() (bool, error) {
func rmDirRecursively(path string) error { func rmDirRecursively(path string) error {
killProcesses := func(signal syscall.Signal) { killProcesses := func(signal syscall.Signal) {
if signal == unix.SIGKILL { if signal == unix.SIGKILL {
if err := ioutil.WriteFile(filepath.Join(path, "cgroup.kill"), []byte("1"), 0600); err == nil { if err := ioutil.WriteFile(filepath.Join(path, "cgroup.kill"), []byte("1"), 0o600); err == nil {
return return
} }
} }

View File

@ -0,0 +1,96 @@
package completion
import (
"fmt"
"io"
"os"
"strings"
"github.com/spf13/cobra"
)
const (
completionDescription = `Generate shell autocompletions.
Valid arguments are bash, zsh, fish and powershell.`
bash = "bash"
zsh = "zsh"
fish = "fish"
powershell = "powershell"
)
var (
file string
noDesc bool
shells = []string{bash, zsh, fish, powershell}
)
// AddCompletionCommand adds the completion command to the given command which should be the root command.
// This command can be used the generate the cobra shell completion scripts for bash, zsh, fish and powershell.
func AddCompletionCommand(rootCmd *cobra.Command) {
completionCmd := &cobra.Command{
Use: fmt.Sprintf("completion [options] {%s}", strings.Join(shells, "|")),
Short: "Generate shell autocompletions",
Long: completionDescription,
ValidArgs: shells,
Args: cobra.ExactValidArgs(1),
RunE: completion,
Example: fmt.Sprintf(`%[1]s completion bash
%[1]s completion zsh -f _%[1]s
%[1]s completion fish --no-desc`, rootCmd.Name()),
// don't show this command to users
Hidden: true,
}
flags := completionCmd.Flags()
fileFlagName := "file"
flags.StringVarP(&file, fileFlagName, "f", "", "Output the completion to file rather than stdout.")
_ = completionCmd.RegisterFlagCompletionFunc(fileFlagName, AutocompleteDefault)
flags.BoolVar(&noDesc, "no-desc", false, "Don't include descriptions in the completion output.")
rootCmd.AddCommand(completionCmd)
}
func completion(cmd *cobra.Command, args []string) error {
var w io.Writer
if file != "" {
file, err := os.Create(file)
if err != nil {
return err
}
defer file.Close()
w = file
} else {
w = os.Stdout
}
var err error
switch args[0] {
case bash:
err = cmd.Root().GenBashCompletionV2(w, !noDesc)
case zsh:
if noDesc {
err = cmd.Root().GenZshCompletionNoDesc(w)
} else {
err = cmd.Root().GenZshCompletion(w)
}
case fish:
err = cmd.Root().GenFishCompletion(w, !noDesc)
case powershell:
if noDesc {
err = cmd.Root().GenPowerShellCompletion(w)
} else {
err = cmd.Root().GenPowerShellCompletionWithDesc(w)
}
}
if err != nil {
return err
}
_, err = io.WriteString(w, fmt.Sprintf(
"# This file is generated with %q; DO NOT EDIT!\n", cmd.CommandPath(),
))
return err
}

View File

@ -1,6 +1,7 @@
package config package config
import ( import (
"errors"
"fmt" "fmt"
"io/fs" "io/fs"
"os" "os"
@ -13,10 +14,10 @@ import (
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/containers/common/libnetwork/types" "github.com/containers/common/libnetwork/types"
"github.com/containers/common/pkg/capabilities" "github.com/containers/common/pkg/capabilities"
"github.com/containers/common/pkg/util"
"github.com/containers/storage/pkg/unshare" "github.com/containers/storage/pkg/unshare"
units "github.com/docker/go-units" units "github.com/docker/go-units"
selinux "github.com/opencontainers/selinux/go-selinux" selinux "github.com/opencontainers/selinux/go-selinux"
"github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -46,6 +47,8 @@ const (
BoltDBStateStore RuntimeStateStore = iota BoltDBStateStore RuntimeStateStore = iota
) )
var validImageVolumeModes = []string{"bind", "tmpfs", "ignore"}
// ProxyEnv is a list of Proxy Environment variables // ProxyEnv is a list of Proxy Environment variables
var ProxyEnv = []string{ var ProxyEnv = []string{
"http_proxy", "http_proxy",
@ -77,7 +80,6 @@ type Config struct {
// ContainersConfig represents the "containers" TOML config table // ContainersConfig represents the "containers" TOML config table
// containers global options for containers tools // containers global options for containers tools
type ContainersConfig struct { type ContainersConfig struct {
// Devices to add to all containers // Devices to add to all containers
Devices []string `toml:"devices,omitempty"` Devices []string `toml:"devices,omitempty"`
@ -294,6 +296,10 @@ type EngineConfig struct {
// Building/committing defaults to OCI. // Building/committing defaults to OCI.
ImageDefaultFormat string `toml:"image_default_format,omitempty"` ImageDefaultFormat string `toml:"image_default_format,omitempty"`
// ImageVolumeMode Tells container engines how to handle the builtin
// image volumes. Acceptable values are "bind", "tmpfs", and "ignore".
ImageVolumeMode string `toml:"image_volume_mode,omitempty"`
// InfraCommand is the command run to start up a pod infra container. // InfraCommand is the command run to start up a pod infra container.
InfraCommand string `toml:"infra_command,omitempty"` InfraCommand string `toml:"infra_command,omitempty"`
@ -604,14 +610,14 @@ func NewConfig(userConfigPath string) (*Config, error) {
// Now, gather the system configs and merge them as needed. // Now, gather the system configs and merge them as needed.
configs, err := systemConfigs() configs, err := systemConfigs()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "finding config on system") return nil, fmt.Errorf("finding config on system: %w", err)
} }
for _, path := range configs { for _, path := range configs {
// Merge changes in later configs with the previous configs. // Merge changes in later configs with the previous configs.
// Each config file that specified fields, will override the // Each config file that specified fields, will override the
// previous fields. // previous fields.
if err = readConfigFromFile(path, config); err != nil { if err = readConfigFromFile(path, config); err != nil {
return nil, errors.Wrapf(err, "reading system config %q", path) return nil, fmt.Errorf("reading system config %q: %w", path, err)
} }
logrus.Debugf("Merged system config %q", path) logrus.Debugf("Merged system config %q", path)
logrus.Tracef("%+v", config) logrus.Tracef("%+v", config)
@ -624,7 +630,7 @@ func NewConfig(userConfigPath string) (*Config, error) {
// readConfigFromFile reads in container config in the specified // readConfigFromFile reads in container config in the specified
// file and then merge changes with the current default. // file and then merge changes with the current default.
if err = readConfigFromFile(userConfigPath, config); err != nil { if err = readConfigFromFile(userConfigPath, config); err != nil {
return nil, errors.Wrapf(err, "reading user config %q", userConfigPath) return nil, fmt.Errorf("reading user config %q: %w", userConfigPath, err)
} }
logrus.Debugf("Merged user config %q", userConfigPath) logrus.Debugf("Merged user config %q", userConfigPath)
logrus.Tracef("%+v", config) logrus.Tracef("%+v", config)
@ -650,7 +656,7 @@ func readConfigFromFile(path string, config *Config) error {
logrus.Tracef("Reading configuration file %q", path) logrus.Tracef("Reading configuration file %q", path)
meta, err := toml.DecodeFile(path, config) meta, err := toml.DecodeFile(path, config)
if err != nil { if err != nil {
return errors.Wrapf(err, "decode configuration %v", path) return fmt.Errorf("decode configuration %v: %w", path, err)
} }
keys := meta.Undecoded() keys := meta.Undecoded()
if len(keys) > 0 { if len(keys) > 0 {
@ -704,7 +710,7 @@ func systemConfigs() ([]string, error) {
path := os.Getenv("CONTAINERS_CONF") path := os.Getenv("CONTAINERS_CONF")
if path != "" { if path != "" {
if _, err := os.Stat(path); err != nil { if _, err := os.Stat(path); err != nil {
return nil, errors.Wrap(err, "CONTAINERS_CONF file") return nil, fmt.Errorf("CONTAINERS_CONF file: %w", err)
} }
return append(configs, path), nil return append(configs, path), nil
} }
@ -779,7 +785,7 @@ func (c *Config) addCAPPrefix() {
// Validate is the main entry point for library configuration validation. // Validate is the main entry point for library configuration validation.
func (c *Config) Validate() error { func (c *Config) Validate() error {
if err := c.Containers.Validate(); err != nil { if err := c.Containers.Validate(); err != nil {
return errors.Wrap(err, "validating containers config") return fmt.Errorf("validating containers config: %w", err)
} }
if !c.Containers.EnableLabeling { if !c.Containers.EnableLabeling {
@ -787,11 +793,11 @@ func (c *Config) Validate() error {
} }
if err := c.Engine.Validate(); err != nil { if err := c.Engine.Validate(); err != nil {
return errors.Wrap(err, "validating engine configs") return fmt.Errorf("validating engine configs: %w", err)
} }
if err := c.Network.Validate(); err != nil { if err := c.Network.Validate(); err != nil {
return errors.Wrap(err, "validating network configs") return fmt.Errorf("validating network configs %w", err)
} }
return nil return nil
@ -821,11 +827,14 @@ func (c *EngineConfig) Validate() error {
return err return err
} }
if err := ValidateImageVolumeMode(c.ImageVolumeMode); err != nil {
return err
}
// Check if the pullPolicy from containers.conf is valid // Check if the pullPolicy from containers.conf is valid
// if it is invalid returns the error // if it is invalid returns the error
pullPolicy := strings.ToLower(c.PullPolicy) pullPolicy := strings.ToLower(c.PullPolicy)
if _, err := ValidatePullPolicy(pullPolicy); err != nil { if _, err := ValidatePullPolicy(pullPolicy); err != nil {
return errors.Wrapf(err, "invalid pull type from containers.conf %q", c.PullPolicy) return fmt.Errorf("invalid pull type from containers.conf %q: %w", c.PullPolicy, err)
} }
return nil return nil
} }
@ -851,11 +860,11 @@ func (c *ContainersConfig) Validate() error {
} }
if c.LogSizeMax >= 0 && c.LogSizeMax < OCIBufSize { if c.LogSizeMax >= 0 && c.LogSizeMax < OCIBufSize {
return errors.Errorf("log size max should be negative or >= %d", OCIBufSize) return fmt.Errorf("log size max should be negative or >= %d", OCIBufSize)
} }
if _, err := units.FromHumanSize(c.ShmSize); err != nil { if _, err := units.FromHumanSize(c.ShmSize); err != nil {
return errors.Errorf("invalid --shm-size %s, %q", c.ShmSize, err) return fmt.Errorf("invalid --shm-size %s, %q", c.ShmSize, err)
} }
return nil return nil
@ -869,11 +878,11 @@ func (c *NetworkConfig) Validate() error {
if &c.DefaultSubnetPools != &DefaultSubnetPools { if &c.DefaultSubnetPools != &DefaultSubnetPools {
for _, pool := range c.DefaultSubnetPools { for _, pool := range c.DefaultSubnetPools {
if pool.Base.IP.To4() == nil { if pool.Base.IP.To4() == nil {
return errors.Errorf("invalid subnet pool ip %q", pool.Base.IP) return fmt.Errorf("invalid subnet pool ip %q", pool.Base.IP)
} }
ones, _ := pool.Base.IPNet.Mask.Size() ones, _ := pool.Base.IPNet.Mask.Size()
if ones > pool.Size { if ones > pool.Size {
return errors.Errorf("invalid subnet pool, size is bigger than subnet %q", &pool.Base.IPNet) return fmt.Errorf("invalid subnet pool, size is bigger than subnet %q", &pool.Base.IPNet)
} }
if pool.Size > 32 { if pool.Size > 32 {
return errors.New("invalid subnet pool size, must be between 0-32") return errors.New("invalid subnet pool size, must be between 0-32")
@ -891,7 +900,7 @@ func (c *NetworkConfig) Validate() error {
} }
} }
return errors.Errorf("invalid cni_plugin_dirs: %s", strings.Join(c.CNIPluginDirs, ",")) return fmt.Errorf("invalid cni_plugin_dirs: %s", strings.Join(c.CNIPluginDirs, ","))
} }
// FindConmon iterates over (*Config).ConmonPath and returns the path // FindConmon iterates over (*Config).ConmonPath and returns the path
@ -928,14 +937,12 @@ func (c *Config) FindConmon() (string, error) {
} }
if foundOutdatedConmon { if foundOutdatedConmon {
return "", errors.Wrapf(ErrConmonOutdated, return "", fmt.Errorf("please update to v%d.%d.%d or later: %w",
"please update to v%d.%d.%d or later", _conmonMinMajorVersion, _conmonMinMinorVersion, _conmonMinPatchVersion, ErrConmonOutdated)
_conmonMinMajorVersion, _conmonMinMinorVersion, _conmonMinPatchVersion)
} }
return "", errors.Wrapf(ErrInvalidArg, return "", fmt.Errorf("could not find a working conmon binary (configured options: %v: %w)",
"could not find a working conmon binary (configured options: %v)", c.Engine.ConmonPath, ErrInvalidArg)
c.Engine.ConmonPath)
} }
// GetDefaultEnv returns the environment variables for the container. // GetDefaultEnv returns the environment variables for the container.
@ -992,7 +999,7 @@ func Device(device string) (src, dst, permissions string, err error) {
switch len(split) { switch len(split) {
case 3: case 3:
if !IsValidDeviceMode(split[2]) { if !IsValidDeviceMode(split[2]) {
return "", "", "", errors.Errorf("invalid device mode: %s", split[2]) return "", "", "", fmt.Errorf("invalid device mode: %s", split[2])
} }
permissions = split[2] permissions = split[2]
fallthrough fallthrough
@ -1001,18 +1008,18 @@ func Device(device string) (src, dst, permissions string, err error) {
permissions = split[1] permissions = split[1]
} else { } else {
if split[1] == "" || split[1][0] != '/' { if split[1] == "" || split[1][0] != '/' {
return "", "", "", errors.Errorf("invalid device mode: %s", split[1]) return "", "", "", fmt.Errorf("invalid device mode: %s", split[1])
} }
dst = split[1] dst = split[1]
} }
fallthrough fallthrough
case 1: case 1:
if !strings.HasPrefix(split[0], "/dev/") { if !strings.HasPrefix(split[0], "/dev/") {
return "", "", "", errors.Errorf("invalid device mode: %s", split[0]) return "", "", "", fmt.Errorf("invalid device mode: %s", split[0])
} }
src = split[0] src = split[0]
default: default:
return "", "", "", errors.Errorf("invalid device specification: %s", device) return "", "", "", fmt.Errorf("invalid device specification: %s", device)
} }
if dst == "" { if dst == "" {
@ -1195,14 +1202,14 @@ func (c *Config) ActiveDestination() (uri, identity string, err error) {
case connEnv != "": case connEnv != "":
d, found := c.Engine.ServiceDestinations[connEnv] d, found := c.Engine.ServiceDestinations[connEnv]
if !found { if !found {
return "", "", errors.Errorf("environment variable CONTAINER_CONNECTION=%q service destination not found", connEnv) return "", "", fmt.Errorf("environment variable CONTAINER_CONNECTION=%q service destination not found", connEnv)
} }
return d.URI, d.Identity, nil return d.URI, d.Identity, nil
case c.Engine.ActiveService != "": case c.Engine.ActiveService != "":
d, found := c.Engine.ServiceDestinations[c.Engine.ActiveService] d, found := c.Engine.ServiceDestinations[c.Engine.ActiveService]
if !found { if !found {
return "", "", errors.Errorf("%q service destination not found", c.Engine.ActiveService) return "", "", fmt.Errorf("%q service destination not found", c.Engine.ActiveService)
} }
return d.URI, d.Identity, nil return d.URI, d.Identity, nil
case c.Engine.RemoteURI != "": case c.Engine.RemoteURI != "":
@ -1232,9 +1239,9 @@ func (c *Config) FindHelperBinary(name string, searchPATH bool) (string, error)
} }
configHint := "To resolve this error, set the helper_binaries_dir key in the `[engine]` section of containers.conf to the directory containing your helper binaries." configHint := "To resolve this error, set the helper_binaries_dir key in the `[engine]` section of containers.conf to the directory containing your helper binaries."
if len(c.Engine.HelperBinariesDir) == 0 { if len(c.Engine.HelperBinariesDir) == 0 {
return "", errors.Errorf("could not find %q because there are no helper binary directories configured. %s", name, configHint) return "", fmt.Errorf("could not find %q because there are no helper binary directories configured. %s", name, configHint)
} }
return "", errors.Errorf("could not find %q in one of %v. %s", name, c.Engine.HelperBinariesDir, configHint) return "", fmt.Errorf("could not find %q in one of %v. %s", name, c.Engine.HelperBinariesDir, configHint)
} }
// ImageCopyTmpDir default directory to store temporary image files during copy // ImageCopyTmpDir default directory to store temporary image files during copy
@ -1253,7 +1260,7 @@ func (c *Config) ImageCopyTmpDir() (string, error) {
} }
} }
return "", errors.Errorf("invalid image_copy_tmp_dir value %q (relative paths are not accepted)", c.Engine.ImageCopyTmpDir) return "", fmt.Errorf("invalid image_copy_tmp_dir value %q (relative paths are not accepted)", c.Engine.ImageCopyTmpDir)
} }
// setupEnv sets the environment variables for the engine // setupEnv sets the environment variables for the engine
@ -1305,3 +1312,14 @@ func (e eventsLogMaxSize) MarshalText() ([]byte, error) {
} }
return []byte(fmt.Sprintf("%d", e)), nil return []byte(fmt.Sprintf("%d", e)), nil
} }
func ValidateImageVolumeMode(mode string) error {
if mode == "" {
return nil
}
if util.StringInSlice(mode, validImageVolumeModes) {
return nil
}
return fmt.Errorf("invalid image volume mode %q required value: %s", mode, strings.Join(validImageVolumeModes, ", "))
}

View File

@ -4,6 +4,7 @@
package config package config
import ( import (
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
@ -11,7 +12,6 @@ import (
"syscall" "syscall"
units "github.com/docker/go-units" units "github.com/docker/go-units"
"github.com/pkg/errors"
) )
// isDirectory tests whether the given path exists and is a directory. It // isDirectory tests whether the given path exists and is a directory. It
@ -44,13 +44,13 @@ func (c *EngineConfig) validatePaths() error {
// shift between runs or even parts of the program. - The OCI runtime // shift between runs or even parts of the program. - The OCI runtime
// uses a different working directory than we do, for example. // uses a different working directory than we do, for example.
if c.StaticDir != "" && !filepath.IsAbs(c.StaticDir) { if c.StaticDir != "" && !filepath.IsAbs(c.StaticDir) {
return errors.Errorf("static directory must be an absolute path - instead got %q", c.StaticDir) return fmt.Errorf("static directory must be an absolute path - instead got %q", c.StaticDir)
} }
if c.TmpDir != "" && !filepath.IsAbs(c.TmpDir) { if c.TmpDir != "" && !filepath.IsAbs(c.TmpDir) {
return errors.Errorf("temporary directory must be an absolute path - instead got %q", c.TmpDir) return fmt.Errorf("temporary directory must be an absolute path - instead got %q", c.TmpDir)
} }
if c.VolumePath != "" && !filepath.IsAbs(c.VolumePath) { if c.VolumePath != "" && !filepath.IsAbs(c.VolumePath) {
return errors.Errorf("volume path must be an absolute path - instead got %q", c.VolumePath) return fmt.Errorf("volume path must be an absolute path - instead got %q", c.VolumePath)
} }
return nil return nil
} }
@ -69,7 +69,7 @@ func (c *ContainersConfig) validateUlimits() error {
for _, u := range c.DefaultUlimits { for _, u := range c.DefaultUlimits {
ul, err := units.ParseUlimit(u) ul, err := units.ParseUlimit(u)
if err != nil { if err != nil {
return errors.Wrapf(err, "unrecognized ulimit %s", u) return fmt.Errorf("unrecognized ulimit %s: %w", u, err)
} }
_, err = ul.GetRlimit() _, err = ul.GetRlimit()
if err != nil { if err != nil {
@ -97,7 +97,7 @@ func (c *ContainersConfig) validateTZ() error {
} }
} }
return errors.Errorf( return fmt.Errorf(
"find timezone %s in paths: %s", "find timezone %s in paths: %s",
c.TZ, strings.Join(lookupPaths, ", "), c.TZ, strings.Join(lookupPaths, ", "),
) )
@ -106,7 +106,7 @@ func (c *ContainersConfig) validateTZ() error {
func (c *ContainersConfig) validateUmask() error { func (c *ContainersConfig) validateUmask() error {
validUmask := regexp.MustCompile(`^[0-7]{1,4}$`) validUmask := regexp.MustCompile(`^[0-7]{1,4}$`)
if !validUmask.MatchString(c.Umask) { if !validUmask.MatchString(c.Umask) {
return errors.Errorf("not a valid umask %s", c.Umask) return fmt.Errorf("not a valid umask %s", c.Umask)
} }
return nil return nil
} }

View File

@ -434,6 +434,16 @@ default_sysctls = [
# #
#image_parallel_copies = 0 #image_parallel_copies = 0
# Tells container engines how to handle the builtin image volumes.
# * bind: An anonymous named volume will be created and mounted
# into the container.
# * tmpfs: The volume is mounted onto the container as a tmpfs,
# which allows users to create content that disappears when
# the container is stopped.
# * ignore: All volumes are just ignored and no action is taken.
#
#image_volume_mode = ""
# Default command to run the infra container # Default command to run the infra container
# #
#infra_command = "/pause" #infra_command = "/pause"

View File

@ -2,6 +2,7 @@ package config
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"net" "net"
"os" "os"
@ -19,7 +20,6 @@ import (
"github.com/containers/storage/pkg/unshare" "github.com/containers/storage/pkg/unshare"
"github.com/containers/storage/types" "github.com/containers/storage/types"
"github.com/opencontainers/selinux/go-selinux" "github.com/opencontainers/selinux/go-selinux"
"github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -35,7 +35,7 @@ const (
// _conmonVersionFormatErr is used when the expected versio-format of conmon // _conmonVersionFormatErr is used when the expected versio-format of conmon
// has changed. // has changed.
_conmonVersionFormatErr = "conmon version changed format" _conmonVersionFormatErr = "conmon version changed format: %w"
// _defaultGraphRoot points to the default path of the graph root. // _defaultGraphRoot points to the default path of the graph root.
_defaultGraphRoot = "/var/lib/containers/storage" _defaultGraphRoot = "/var/lib/containers/storage"
@ -43,26 +43,29 @@ const (
// _defaultTransport is a prefix that we apply to an image name to check // _defaultTransport is a prefix that we apply to an image name to check
// docker hub first for the image. // docker hub first for the image.
_defaultTransport = "docker://" _defaultTransport = "docker://"
// _defaultImageVolumeMode is a mode to handle built-in image volumes.
_defaultImageVolumeMode = "bind"
) )
var ( var (
// DefaultInitPath is the default path to the container-init binary // DefaultInitPath is the default path to the container-init binary.
DefaultInitPath = "/usr/libexec/podman/catatonit" DefaultInitPath = "/usr/libexec/podman/catatonit"
// DefaultInfraImage to use for infra container // DefaultInfraImage is the default image to run as infrastructure containers in pods.
DefaultInfraImage = "" DefaultInfraImage = ""
// DefaultRootlessSHMLockPath is the default path for rootless SHM locks // DefaultRootlessSHMLockPath is the default path for rootless SHM locks.
DefaultRootlessSHMLockPath = "/libpod_rootless_lock" DefaultRootlessSHMLockPath = "/libpod_rootless_lock"
// DefaultDetachKeys is the default keys sequence for detaching a // DefaultDetachKeys is the default keys sequence for detaching a
// container // container.
DefaultDetachKeys = "ctrl-p,ctrl-q" DefaultDetachKeys = "ctrl-p,ctrl-q"
// ErrConmonOutdated indicates the version of conmon found (whether via the configuration or $PATH) // ErrConmonOutdated indicates the version of conmon found (whether via the configuration or $PATH)
// is out of date for the current podman version // is out of date for the current podman version.
ErrConmonOutdated = errors.New("outdated conmon version") ErrConmonOutdated = errors.New("outdated conmon version")
// ErrInvalidArg indicates that an invalid argument was passed // ErrInvalidArg indicates that an invalid argument was passed.
ErrInvalidArg = errors.New("invalid argument") ErrInvalidArg = errors.New("invalid argument")
// DefaultHooksDirs defines the default hooks directory // DefaultHooksDirs defines the default hooks directory.
DefaultHooksDirs = []string{"/usr/share/containers/oci/hooks.d"} DefaultHooksDirs = []string{"/usr/share/containers/oci/hooks.d"}
// DefaultCapabilities for the default_capabilities option in the containers.conf file // DefaultCapabilities is the default for the default_capabilities option in the containers.conf file.
DefaultCapabilities = []string{ DefaultCapabilities = []string{
"CAP_AUDIT_WRITE", "CAP_AUDIT_WRITE",
"CAP_CHOWN", "CAP_CHOWN",
@ -80,7 +83,7 @@ var (
"CAP_SYS_CHROOT", "CAP_SYS_CHROOT",
} }
// It may seem a bit unconventional, but it is necessary to do so // Search these locations in which CNIPlugins can be installed.
DefaultCNIPluginDirs = []string{ DefaultCNIPluginDirs = []string{
"/usr/local/libexec/cni", "/usr/local/libexec/cni",
"/usr/libexec/cni", "/usr/libexec/cni",
@ -98,7 +101,7 @@ var (
} }
// additionalHelperBinariesDir is an extra helper binaries directory that // additionalHelperBinariesDir is an extra helper binaries directory that
// should be set during link-time, if different packagers put their // should be set during link-time, if different packagers put their
// helper binary in a different location // helper binary in a different location.
additionalHelperBinariesDir string additionalHelperBinariesDir string
) )
@ -118,13 +121,13 @@ const (
// InstallPrefix is the prefix where podman will be installed. // InstallPrefix is the prefix where podman will be installed.
// It can be overridden at build time. // It can be overridden at build time.
_installPrefix = "/usr" _installPrefix = "/usr"
// CgroupfsCgroupsManager represents cgroupfs native cgroup manager // CgroupfsCgroupsManager represents cgroupfs native cgroup manager.
CgroupfsCgroupsManager = "cgroupfs" CgroupfsCgroupsManager = "cgroupfs"
// DefaultApparmorProfile specifies the default apparmor profile for the container. // DefaultApparmorProfile specifies the default apparmor profile for the container.
DefaultApparmorProfile = apparmor.Profile DefaultApparmorProfile = apparmor.Profile
// DefaultHostsFile is the default path to the hosts file // DefaultHostsFile is the default path to the hosts file.
DefaultHostsFile = "/etc/hosts" DefaultHostsFile = "/etc/hosts"
// SystemdCgroupsManager represents systemd native cgroup manager // SystemdCgroupsManager represents systemd native cgroup manager.
SystemdCgroupsManager = "systemd" SystemdCgroupsManager = "systemd"
// DefaultLogSizeMax is the default value for the maximum log size // DefaultLogSizeMax is the default value for the maximum log size
// allowed for a container. Negative values mean that no limit is imposed. // allowed for a container. Negative values mean that no limit is imposed.
@ -133,9 +136,9 @@ const (
// before rotation. // before rotation.
DefaultEventsLogSizeMax = uint64(1000000) DefaultEventsLogSizeMax = uint64(1000000)
// DefaultPidsLimit is the default value for maximum number of processes // DefaultPidsLimit is the default value for maximum number of processes
// allowed inside a container // allowed inside a container.
DefaultPidsLimit = 2048 DefaultPidsLimit = 2048
// DefaultPullPolicy pulls the image if it does not exist locally // DefaultPullPolicy pulls the image if it does not exist locally.
DefaultPullPolicy = "missing" DefaultPullPolicy = "missing"
// DefaultSignaturePolicyPath is the default value for the // DefaultSignaturePolicyPath is the default value for the
// policy.json file. // policy.json file.
@ -146,11 +149,11 @@ const (
// DefaultRootlessSignaturePolicyPath is the location within // DefaultRootlessSignaturePolicyPath is the location within
// XDG_CONFIG_HOME of the rootless policy.json file. // XDG_CONFIG_HOME of the rootless policy.json file.
DefaultRootlessSignaturePolicyPath = "containers/policy.json" DefaultRootlessSignaturePolicyPath = "containers/policy.json"
// DefaultShmSize default value // DefaultShmSize is the default upper limit on the size of tmpfs mounts.
DefaultShmSize = "65536k" DefaultShmSize = "65536k"
// DefaultUserNSSize default value // DefaultUserNSSize indicates the default number of UIDs allocated for user namespace within a container.
DefaultUserNSSize = 65536 DefaultUserNSSize = 65536
// OCIBufSize limits maximum LogSizeMax // OCIBufSize limits maximum LogSizeMax.
OCIBufSize = 8192 OCIBufSize = 8192
// SeccompOverridePath if this exists it overrides the default seccomp path. // SeccompOverridePath if this exists it overrides the default seccomp path.
SeccompOverridePath = _etcDir + "/containers/seccomp.json" SeccompOverridePath = _etcDir + "/containers/seccomp.json"
@ -158,7 +161,7 @@ const (
SeccompDefaultPath = _installPrefix + "/share/containers/seccomp.json" SeccompDefaultPath = _installPrefix + "/share/containers/seccomp.json"
) )
// DefaultConfig defines the default values from containers.conf // DefaultConfig defines the default values from containers.conf.
func DefaultConfig() (*Config, error) { func DefaultConfig() (*Config, error) {
defaultEngineConfig, err := defaultConfigFromMemory() defaultEngineConfig, err := defaultConfigFromMemory()
if err != nil { if err != nil {
@ -294,6 +297,7 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
} }
c.HooksDir = DefaultHooksDirs c.HooksDir = DefaultHooksDirs
c.ImageDefaultTransport = _defaultTransport c.ImageDefaultTransport = _defaultTransport
c.ImageVolumeMode = _defaultImageVolumeMode
c.StateType = BoltDBStateStore c.StateType = BoltDBStateStore
c.ImageBuildFormat = "oci" c.ImageBuildFormat = "oci"
@ -350,7 +354,7 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
"/usr/local/bin/krun", "/usr/local/bin/krun",
}, },
} }
// Needs to be called after populating c.OCIRuntimes // Needs to be called after populating c.OCIRuntimes.
c.OCIRuntime = c.findRuntime() c.OCIRuntime = c.findRuntime()
c.ConmonEnvVars = []string{ c.ConmonEnvVars = []string{
@ -411,8 +415,8 @@ func defaultTmpDir() (string, error) {
if !os.IsExist(err) { if !os.IsExist(err) {
return "", err return "", err
} else if err := os.Chmod(libpodRuntimeDir, 0o700|os.ModeSticky); err != nil { } else if err := os.Chmod(libpodRuntimeDir, 0o700|os.ModeSticky); err != nil {
// The directory already exist, just set the sticky bit // The directory already exists, so we try to make sure it's private and has the sticky bit set on it.
return "", errors.Wrap(err, "set sticky bit on") return "", fmt.Errorf("set sticky bit on: %w", err)
} }
} }
return filepath.Join(libpodRuntimeDir, "tmp"), nil return filepath.Join(libpodRuntimeDir, "tmp"), nil
@ -435,7 +439,7 @@ func probeConmon(conmonBinary string) error {
} }
major, err := strconv.Atoi(matches[1]) major, err := strconv.Atoi(matches[1])
if err != nil { if err != nil {
return errors.Wrap(err, _conmonVersionFormatErr) return fmt.Errorf(_conmonVersionFormatErr, err)
} }
if major < _conmonMinMajorVersion { if major < _conmonMinMajorVersion {
return ErrConmonOutdated return ErrConmonOutdated
@ -446,7 +450,7 @@ func probeConmon(conmonBinary string) error {
minor, err := strconv.Atoi(matches[2]) minor, err := strconv.Atoi(matches[2])
if err != nil { if err != nil {
return errors.Wrap(err, _conmonVersionFormatErr) return fmt.Errorf(_conmonVersionFormatErr, err)
} }
if minor < _conmonMinMinorVersion { if minor < _conmonMinMinorVersion {
return ErrConmonOutdated return ErrConmonOutdated
@ -457,7 +461,7 @@ func probeConmon(conmonBinary string) error {
patch, err := strconv.Atoi(matches[3]) patch, err := strconv.Atoi(matches[3])
if err != nil { if err != nil {
return errors.Wrap(err, _conmonVersionFormatErr) return fmt.Errorf(_conmonVersionFormatErr, err)
} }
if patch < _conmonMinPatchVersion { if patch < _conmonMinPatchVersion {
return ErrConmonOutdated return ErrConmonOutdated
@ -469,7 +473,7 @@ func probeConmon(conmonBinary string) error {
return nil return nil
} }
// NetNS returns the default network namespace // NetNS returns the default network namespace.
func (c *Config) NetNS() string { func (c *Config) NetNS() string {
return c.Containers.NetNS return c.Containers.NetNS
} }
@ -478,7 +482,7 @@ func (c EngineConfig) EventsLogMaxSize() uint64 {
return uint64(c.EventsLogFileMaxSize) return uint64(c.EventsLogFileMaxSize)
} }
// SecurityOptions returns the default security options // SecurityOptions returns the default security options.
func (c *Config) SecurityOptions() []string { func (c *Config) SecurityOptions() []string {
securityOpts := []string{} securityOpts := []string{}
if c.Containers.SeccompProfile != "" && c.Containers.SeccompProfile != SeccompDefaultPath { if c.Containers.SeccompProfile != "" && c.Containers.SeccompProfile != SeccompDefaultPath {
@ -493,82 +497,82 @@ func (c *Config) SecurityOptions() []string {
return securityOpts return securityOpts
} }
// Sysctls returns the default sysctls // Sysctls returns the default sysctls to set in containers.
func (c *Config) Sysctls() []string { func (c *Config) Sysctls() []string {
return c.Containers.DefaultSysctls return c.Containers.DefaultSysctls
} }
// Volumes returns the default additional volumes for containersvolumes // Volumes returns the default set of volumes that should be mounted in containers.
func (c *Config) Volumes() []string { func (c *Config) Volumes() []string {
return c.Containers.Volumes return c.Containers.Volumes
} }
// Devices returns the default additional devices for containers // Devices returns the default additional devices for containers.
func (c *Config) Devices() []string { func (c *Config) Devices() []string {
return c.Containers.Devices return c.Containers.Devices
} }
// DNSServers returns the default DNS servers to add to resolv.conf in containers // DNSServers returns the default DNS servers to add to resolv.conf in containers.
func (c *Config) DNSServers() []string { func (c *Config) DNSServers() []string {
return c.Containers.DNSServers return c.Containers.DNSServers
} }
// DNSSerches returns the default DNS searches to add to resolv.conf in containers // DNSSerches returns the default DNS searches to add to resolv.conf in containers.
func (c *Config) DNSSearches() []string { func (c *Config) DNSSearches() []string {
return c.Containers.DNSSearches return c.Containers.DNSSearches
} }
// DNSOptions returns the default DNS options to add to resolv.conf in containers // DNSOptions returns the default DNS options to add to resolv.conf in containers.
func (c *Config) DNSOptions() []string { func (c *Config) DNSOptions() []string {
return c.Containers.DNSOptions return c.Containers.DNSOptions
} }
// Env returns the default additional environment variables to add to containers // Env returns the default additional environment variables to add to containers.
func (c *Config) Env() []string { func (c *Config) Env() []string {
return c.Containers.Env return c.Containers.Env
} }
// InitPath returns the default init path to add to containers // InitPath returns location where init program added to containers when users specify the --init flag.
func (c *Config) InitPath() string { func (c *Config) InitPath() string {
return c.Containers.InitPath return c.Containers.InitPath
} }
// IPCNS returns the default IPC Namespace configuration to run containers with // IPCNS returns the default IPC Namespace configuration to run containers with.
func (c *Config) IPCNS() string { func (c *Config) IPCNS() string {
return c.Containers.IPCNS return c.Containers.IPCNS
} }
// PIDNS returns the default PID Namespace configuration to run containers with // PIDNS returns the default PID Namespace configuration to run containers with.
func (c *Config) PidNS() string { func (c *Config) PidNS() string {
return c.Containers.PidNS return c.Containers.PidNS
} }
// CgroupNS returns the default Cgroup Namespace configuration to run containers with // CgroupNS returns the default Cgroup Namespace configuration to run containers with.
func (c *Config) CgroupNS() string { func (c *Config) CgroupNS() string {
return c.Containers.CgroupNS return c.Containers.CgroupNS
} }
// Cgroups returns whether to containers with cgroup confinement // Cgroups returns whether to run containers in their own control groups, as configured by the "cgroups" setting in containers.conf.
func (c *Config) Cgroups() string { func (c *Config) Cgroups() string {
return c.Containers.Cgroups return c.Containers.Cgroups
} }
// UTSNS returns the default UTS Namespace configuration to run containers with // UTSNS returns the default UTS Namespace configuration to run containers with.
func (c *Config) UTSNS() string { func (c *Config) UTSNS() string {
return c.Containers.UTSNS return c.Containers.UTSNS
} }
// ShmSize returns the default size for temporary file systems to use in containers // ShmSize returns the default size for temporary file systems to use in containers.
func (c *Config) ShmSize() string { func (c *Config) ShmSize() string {
return c.Containers.ShmSize return c.Containers.ShmSize
} }
// Ulimits returns the default ulimits to use in containers // Ulimits returns the default ulimits to use in containers.
func (c *Config) Ulimits() []string { func (c *Config) Ulimits() []string {
return c.Containers.DefaultUlimits return c.Containers.DefaultUlimits
} }
// PidsLimit returns the default maximum number of pids to use in containers // PidsLimit returns the default maximum number of pids to use in containers.
func (c *Config) PidsLimit() int64 { func (c *Config) PidsLimit() int64 {
if unshare.IsRootless() { if unshare.IsRootless() {
if c.Engine.CgroupManager != SystemdCgroupsManager { if c.Engine.CgroupManager != SystemdCgroupsManager {
@ -583,12 +587,12 @@ func (c *Config) PidsLimit() int64 {
return c.Containers.PidsLimit return c.Containers.PidsLimit
} }
// DetachKeys returns the default detach keys to detach from a container // DetachKeys returns the default detach keys to detach from a container.
func (c *Config) DetachKeys() string { func (c *Config) DetachKeys() string {
return c.Engine.DetachKeys return c.Engine.DetachKeys
} }
// Tz returns the timezone in the container // TZ returns the timezone to set in containers.
func (c *Config) TZ() string { func (c *Config) TZ() string {
return c.Containers.TZ return c.Containers.TZ
} }
@ -598,17 +602,17 @@ func (c *Config) Umask() string {
} }
// LogDriver returns the logging driver to be used // LogDriver returns the logging driver to be used
// currently k8s-file or journald // currently k8s-file or journald.
func (c *Config) LogDriver() string { func (c *Config) LogDriver() string {
return c.Containers.LogDriver return c.Containers.LogDriver
} }
// MachineEnabled returns if podman is running inside a VM or not // MachineEnabled returns if podman is running inside a VM or not.
func (c *Config) MachineEnabled() bool { func (c *Config) MachineEnabled() bool {
return c.Engine.MachineEnabled return c.Engine.MachineEnabled
} }
// MachineVolumes returns volumes to mount into the VM // MachineVolumes returns volumes to mount into the VM.
func (c *Config) MachineVolumes() ([]string, error) { func (c *Config) MachineVolumes() ([]string, error) {
return machineVolumes(c.Machine.Volumes) return machineVolumes(c.Machine.Volumes)
} }
@ -619,10 +623,10 @@ func machineVolumes(volumes []string) ([]string, error) {
vol := os.ExpandEnv(v) vol := os.ExpandEnv(v)
split := strings.Split(vol, ":") split := strings.Split(vol, ":")
if len(split) < 2 || len(split) > 3 { if len(split) < 2 || len(split) > 3 {
return nil, errors.Errorf("invalid machine volume %s, 2 or 3 fields required", v) return nil, fmt.Errorf("invalid machine volume %s, 2 or 3 fields required", v)
} }
if split[0] == "" || split[1] == "" { if split[0] == "" || split[1] == "" {
return nil, errors.Errorf("invalid machine volume %s, fields must container data", v) return nil, fmt.Errorf("invalid machine volume %s, fields must container data", v)
} }
translatedVolumes = append(translatedVolumes, vol) translatedVolumes = append(translatedVolumes, vol)
} }

View File

@ -2,8 +2,6 @@ package config
import ( import (
"fmt" "fmt"
"github.com/pkg/errors"
) )
// PullPolicy determines how and which images are being pulled from a container // PullPolicy determines how and which images are being pulled from a container
@ -63,7 +61,7 @@ func (p PullPolicy) Validate() error {
case PullPolicyAlways, PullPolicyMissing, PullPolicyNewer, PullPolicyNever: case PullPolicyAlways, PullPolicyMissing, PullPolicyNewer, PullPolicyNever:
return nil return nil
default: default:
return errors.Errorf("unsupported pull policy %d", p) return fmt.Errorf("unsupported pull policy %d", p)
} }
} }
@ -85,7 +83,7 @@ func ParsePullPolicy(s string) (PullPolicy, error) {
case "never", "Never": case "never", "Never":
return PullPolicyNever, nil return PullPolicyNever, nil
default: default:
return PullPolicyUnsupported, errors.Errorf("unsupported pull policy %q", s) return PullPolicyUnsupported, fmt.Errorf("unsupported pull policy %q", s)
} }
} }

3
vendor/modules.txt vendored
View File

@ -109,9 +109,10 @@ github.com/containers/buildah/pkg/rusage
github.com/containers/buildah/pkg/sshagent github.com/containers/buildah/pkg/sshagent
github.com/containers/buildah/pkg/util github.com/containers/buildah/pkg/util
github.com/containers/buildah/util github.com/containers/buildah/util
# github.com/containers/common v0.48.1-0.20220512112240-7536bf6ff9b1 # github.com/containers/common v0.48.1-0.20220523155016-2fd37da97824
## explicit ## explicit
github.com/containers/common/libimage github.com/containers/common/libimage
github.com/containers/common/libimage/define
github.com/containers/common/libimage/manifests github.com/containers/common/libimage/manifests
github.com/containers/common/libnetwork/cni github.com/containers/common/libnetwork/cni
github.com/containers/common/libnetwork/etchosts github.com/containers/common/libnetwork/etchosts