diff options
49 files changed, 939 insertions, 229 deletions
@@ -397,6 +397,10 @@ install-podman-remote-%-docs: podman-remote docs $(MANPAGES) man-page-check: hack/man-page-checker +.PHONY: swagger-check +swagger-check: + hack/swagger-check + .PHONY: codespell codespell: codespell -S bin,vendor,.git,go.sum,changelog.txt,seccomp.json,.cirrus.yml,"*.xz,*.gz,*.tar,*.tgz,bin2img,*ico,*.png,*.1,*.5,copyimg,*.orig,apidoc.go" -L uint,iff,od,seeked,splitted,marge,ERRO,hist -w @@ -624,7 +628,7 @@ validate.completions: completions/bash/podman if [ -x /bin/zsh ]; then /bin/zsh completions/zsh/_podman; fi .PHONY: validate -validate: gofmt lint .gitvalidation validate.completions man-page-check +validate: gofmt lint .gitvalidation validate.completions man-page-check swagger-check .PHONY: build-all-new-commits build-all-new-commits: @@ -5,7 +5,7 @@ Libpod provides a library for applications looking to use the Container Pod concept, popularized by Kubernetes. Libpod also contains the Pod Manager tool `(Podman)`. Podman manages pods, containers, container images, and container volumes. -* [Latest Version: 1.8.2](https://github.com/containers/libpod/releases/latest) +* [Latest Version: 1.9.0](https://github.com/containers/libpod/releases/latest) * [Continuous Integration:](contrib/cirrus/README.md) [![Build Status](https://api.cirrus-ci.com/github/containers/libpod.svg)](https://cirrus-ci.com/github/containers/libpod/master) * [GoDoc: ![GoDoc](https://godoc.org/github.com/containers/libpod/libpod?status.svg)](https://godoc.org/github.com/containers/libpod/libpod) * Automated continuous release downloads (including remote-client): diff --git a/cmd/podman/containers_prune.go b/cmd/podman/containers_prune.go index cd9817e7e..3953a489d 100644 --- a/cmd/podman/containers_prune.go +++ b/cmd/podman/containers_prune.go @@ -19,12 +19,12 @@ var ( pruneContainersDescription = ` podman container prune - Removes all exited containers + Removes all stopped | exited containers ` _pruneContainersCommand = &cobra.Command{ Use: "prune", Args: noSubArgs, - Short: "Remove all stopped containers", + Short: "Remove all stopped | exited containers", Long: pruneContainersDescription, RunE: func(cmd *cobra.Command, args []string) error { pruneContainersCommand.InputArgs = args diff --git a/cmd/podman/runlabel.go b/cmd/podman/runlabel.go index 1ec4da650..193cc5aec 100644 --- a/cmd/podman/runlabel.go +++ b/cmd/podman/runlabel.go @@ -13,11 +13,11 @@ import ( "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/image" - "github.com/containers/libpod/pkg/util" "github.com/containers/libpod/utils" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "github.com/spf13/pflag" ) var ( @@ -157,7 +157,7 @@ func runlabelCmd(c *cliconfig.RunlabelValues) error { return errors.Errorf("%s does not have a label of %s", runlabelImage, label) } - globalOpts := util.GetGlobalOpts(c) + globalOpts := GetGlobalOpts(c) cmd, env, err := shared.GenerateRunlabelCommand(runLabel, imageName, c.Name, opts, extraArgs, globalOpts) if err != nil { return err @@ -193,3 +193,32 @@ func runlabelCmd(c *cliconfig.RunlabelValues) error { return utils.ExecCmdWithStdStreams(stdIn, stdOut, stdErr, env, cmd[0], cmd[1:]...) } + +// GetGlobalOpts checks all global flags and generates the command string +func GetGlobalOpts(c *cliconfig.RunlabelValues) string { + globalFlags := map[string]bool{ + "cgroup-manager": true, "cni-config-dir": true, "conmon": true, "default-mounts-file": true, + "hooks-dir": true, "namespace": true, "root": true, "runroot": true, + "runtime": true, "storage-driver": true, "storage-opt": true, "syslog": true, + "trace": true, "network-cmd-path": true, "config": true, "cpu-profile": true, + "log-level": true, "tmpdir": true} + const stringSliceType string = "stringSlice" + + var optsCommand []string + c.PodmanCommand.Command.Flags().VisitAll(func(f *pflag.Flag) { + if !f.Changed { + return + } + if _, exist := globalFlags[f.Name]; exist { + if f.Value.Type() == stringSliceType { + flagValue := strings.TrimSuffix(strings.TrimPrefix(f.Value.String(), "["), "]") + for _, value := range strings.Split(flagValue, ",") { + optsCommand = append(optsCommand, fmt.Sprintf("--%s %s", f.Name, value)) + } + } else { + optsCommand = append(optsCommand, fmt.Sprintf("--%s %s", f.Name, f.Value.String())) + } + } + }) + return strings.Join(optsCommand, " ") +} diff --git a/cmd/podmanV2/Makefile b/cmd/podmanV2/Makefile index 01d551212..c951cbdd9 100644 --- a/cmd/podmanV2/Makefile +++ b/cmd/podmanV2/Makefile @@ -1,10 +1,10 @@ all: podman podman-remote podman: - CGO_ENABLED=1 GO111MODULE=off go build -tags 'ABISupport systemd varlink seccomp' + CGO_ENABLED=1 GO111MODULE=off go build -tags 'ABISupport systemd varlink seccomp selinux' podman-remote: - CGO_ENABLED=1 GO111MODULE=off go build -tags '!ABISupport systemd seccomp' -o podmanV2-remote + CGO_ENABLED=1 GO111MODULE=off go build -tags '!ABISupport systemd seccomp selinux' -o podmanV2-remote clean: rm podmanV2 podmanV2-remote diff --git a/cmd/podmanV2/common/create.go b/cmd/podmanV2/common/create.go index e2eb8cbda..ecaaf38fb 100644 --- a/cmd/podmanV2/common/create.go +++ b/cmd/podmanV2/common/create.go @@ -6,7 +6,6 @@ import ( buildahcli "github.com/containers/buildah/pkg/cli" "github.com/containers/common/pkg/config" - "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/sirupsen/logrus" "github.com/spf13/pflag" ) @@ -214,22 +213,22 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet { ) createFlags.StringVar( &cf.HealthInterval, - "health-interval", cliconfig.DefaultHealthCheckInterval, + "health-interval", DefaultHealthCheckInterval, "set an interval for the healthchecks (a value of disable results in no automatic timer setup)", ) createFlags.UintVar( &cf.HealthRetries, - "health-retries", cliconfig.DefaultHealthCheckRetries, + "health-retries", DefaultHealthCheckRetries, "the number of retries allowed before a healthcheck is considered to be unhealthy", ) createFlags.StringVar( &cf.HealthStartPeriod, - "health-start-period", cliconfig.DefaultHealthCheckStartPeriod, + "health-start-period", DefaultHealthCheckStartPeriod, "the initialization time needed for a container to bootstrap", ) createFlags.StringVar( &cf.HealthTimeout, - "health-timeout", cliconfig.DefaultHealthCheckTimeout, + "health-timeout", DefaultHealthCheckTimeout, "the maximum time allowed to complete the healthcheck before an interval is considered failed", ) createFlags.StringVarP( @@ -244,7 +243,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet { ) createFlags.StringVar( &cf.ImageVolume, - "image-volume", cliconfig.DefaultImageVolume, + "image-volume", DefaultImageVolume, `Tells podman how to handle the builtin image volumes ("bind"|"tmpfs"|"ignore")`, ) createFlags.BoolVar( diff --git a/cmd/podmanV2/common/default.go b/cmd/podmanV2/common/default.go index b71fcb6f0..bd793f168 100644 --- a/cmd/podmanV2/common/default.go +++ b/cmd/podmanV2/common/default.go @@ -12,6 +12,19 @@ import ( "github.com/opencontainers/selinux/go-selinux" ) +var ( + // DefaultHealthCheckInterval default value + DefaultHealthCheckInterval = "30s" + // DefaultHealthCheckRetries default value + DefaultHealthCheckRetries uint = 3 + // DefaultHealthCheckStartPeriod default value + DefaultHealthCheckStartPeriod = "0s" + // DefaultHealthCheckTimeout default value + DefaultHealthCheckTimeout = "30s" + // DefaultImageVolume default value + DefaultImageVolume = "bind" +) + // TODO these options are directly embedded into many of the CLI cobra values, as such // this approach will not work in a remote client. so we will need to likely do something like a // supported and unsupported approach here and backload these options into the specgen diff --git a/cmd/podmanV2/containers/prune.go b/cmd/podmanV2/containers/prune.go new file mode 100644 index 000000000..2d3af5d1d --- /dev/null +++ b/cmd/podmanV2/containers/prune.go @@ -0,0 +1,86 @@ +package containers + +import ( + "bufio" + "context" + "fmt" + "net/url" + "os" + "strings" + + "github.com/containers/libpod/cmd/podmanV2/registry" + "github.com/containers/libpod/cmd/podmanV2/utils" + "github.com/containers/libpod/pkg/domain/entities" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +var ( + pruneDescription = fmt.Sprintf(`podman container prune + + Removes all stopped | exited containers`) + pruneCommand = &cobra.Command{ + Use: "prune [flags]", + Short: "Remove all stopped | exited containers", + Long: pruneDescription, + RunE: prune, + Example: `podman container prune`, + } + force bool + filter = []string{} +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: pruneCommand, + Parent: containerCmd, + }) + flags := pruneCommand.Flags() + flags.BoolVarP(&force, "force", "f", false, "Do not prompt for confirmation. The default is false") + flags.StringArrayVar(&filter, "filter", []string{}, "Provide filter values (e.g. 'label=<key>=<value>')") +} + +func prune(cmd *cobra.Command, args []string) error { + var ( + errs utils.OutputErrors + pruneOptions = entities.ContainerPruneOptions{} + ) + if len(args) > 0 { + return errors.Errorf("`%s` takes no arguments", cmd.CommandPath()) + } + if !force { + reader := bufio.NewReader(os.Stdin) + fmt.Println("WARNING! This will remove all stopped containers.") + fmt.Print("Are you sure you want to continue? [y/N] ") + answer, err := reader.ReadString('\n') + if err != nil { + return errors.Wrapf(err, "error reading input") + } + if strings.ToLower(answer)[0] != 'y' { + return nil + } + } + + // TODO Remove once filter refactor is finished and url.Values done. + for _, f := range filter { + t := strings.SplitN(f, "=", 2) + pruneOptions.Filters = make(url.Values) + if len(t) < 2 { + return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f) + } + pruneOptions.Filters.Add(t[0], t[1]) + } + responses, err := registry.ContainerEngine().ContainerPrune(context.Background(), pruneOptions) + + if err != nil { + return err + } + for k := range responses.ID { + fmt.Println(k) + } + for _, v := range responses.Err { + errs = append(errs, v) + } + return errs.PrintErrors() +} @@ -10,7 +10,7 @@ require ( github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921 github.com/containernetworking/plugins v0.8.5 github.com/containers/buildah v1.14.8 - github.com/containers/common v0.8.1 + github.com/containers/common v0.9.1 github.com/containers/conmon v2.0.14+incompatible github.com/containers/image/v5 v5.4.3 github.com/containers/psgo v1.4.0 @@ -65,8 +65,9 @@ github.com/containernetworking/plugins v0.8.5 h1:pCvEMrFf7yzJI8+/D/7jkvE96KD52b7 github.com/containernetworking/plugins v0.8.5/go.mod h1:UZ2539umj8djuRQmBxuazHeJbYrLV8BSBejkk+she6o= github.com/containers/buildah v1.14.8 h1:JbMI0QSOmyZ30Mr2633uCXAj+Fajgh/EFS9xX/Y14oQ= github.com/containers/buildah v1.14.8/go.mod h1:ytEjHJQnRXC1ygXMyc0FqYkjcoCydqBQkOdxbH563QU= -github.com/containers/common v0.8.1 h1:1IUwAtZ4mC7GYRr4AC23cHf2oXCuoLzTUoSzIkSgnYw= github.com/containers/common v0.8.1/go.mod h1:VxDJbaA1k6N1TNv9Rt6bQEF4hyKVHNfOfGA5L91ADEs= +github.com/containers/common v0.9.1 h1:S5lkpnycTI29YzpNJ4RLv49g8sksgYNRNsugPmzQCR8= +github.com/containers/common v0.9.1/go.mod h1:9YGKPwu6NFYQG2NtSP9bRhNGA8mgd1mUCCkOU2tr+Pc= github.com/containers/conmon v2.0.14+incompatible h1:knU1O1QxXy5YxtjMQVKEyCajROaehizK9FHaICl+P5Y= github.com/containers/conmon v2.0.14+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/image/v5 v5.4.3 h1:zn2HR7uu4hpvT5QQHgjqonOzKDuM1I1UHUEmzZT5sbs= @@ -168,7 +169,6 @@ github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14j github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -217,7 +217,6 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -259,7 +258,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -272,9 +270,7 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mistifyio/go-zfs v2.1.1+incompatible h1:gAMO1HM9xBRONLHHYnu5iFsOJUiJdNZo6oqSENd4eW8= github.com/mistifyio/go-zfs v2.1.1+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/moby/sys/mountinfo v0.1.0/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o= github.com/moby/vpnkit v0.3.1-0.20200304131818-6bc1679a048d/go.mod h1:KyjUrL9cb6ZSNNAUwZfqRjhwwgJ3BJN+kXh0t43WTUQ= @@ -285,7 +281,6 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE= github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= @@ -331,7 +326,6 @@ github.com/opencontainers/runtime-spec v0.1.2-0.20190618234442-a950415649c7/go.m github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/opencontainers/runtime-tools v0.9.0 h1:FYgwVsKRI/H9hU32MJ/4MLOzXWodKK5zsQavY8NPMkU= github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/opencontainers/selinux v1.4.0 h1:cpiX/2wWIju/6My60T6/z9CxNG7c8xTQyEmA9fChpUo= github.com/opencontainers/selinux v1.4.0/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g= github.com/opencontainers/selinux v1.5.1 h1:jskKwSMFYqyTrHEuJgQoUlTcId0av64S6EWObrIfn5Y= github.com/opencontainers/selinux v1.5.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g= @@ -343,7 +337,6 @@ github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsq github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913 h1:TnbXhKzrTOyuvWrjI8W6pcoI9XPbLHFXCdN2dtUw7Rw= github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913/go.mod h1:J6OG6YJVEWopen4avK3VNQSnALmmjvniMmni/YFYAwc= -github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.0.0-20190227000051-27936f6d90f9/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -398,20 +391,16 @@ github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.7 h1:FfTH+vuMXOas8jmfb5/M7dzEYx7LpcLb7a0LPe34uOU= github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -476,7 +465,6 @@ golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= @@ -508,7 +496,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -519,7 +506,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -546,7 +532,6 @@ golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 h1:TC0v2RSO1u2kn1ZugjrFXkRZAEaqMN/RW+OTZkBzmLE= @@ -557,7 +542,6 @@ golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5f golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -572,7 +556,6 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72 h1:bw9doJza/SFBEweII/rHQh338oozWyiFsBRHtrflcws= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= diff --git a/hack/swagger-check b/hack/swagger-check new file mode 100755 index 000000000..d564b6554 --- /dev/null +++ b/hack/swagger-check @@ -0,0 +1,317 @@ +#!/usr/bin/perl +# +# swagger-check - Look for inconsistencies between swagger and source code +# +package LibPod::SwaggerCheck; + +use v5.14; +use strict; +use warnings; + +use File::Find; + +(our $ME = $0) =~ s|.*/||; +(our $VERSION = '$Revision: 1.7 $ ') =~ tr/[0-9].//cd; + +# For debugging, show data structures using DumpTree($var) +#use Data::TreeDumper; $Data::TreeDumper::Displayaddress = 0; + +############################################################################### +# BEGIN user-customizable section + +our $Default_Dir = 'pkg/api/server'; + +# END user-customizable section +############################################################################### + +############################################################################### +# BEGIN boilerplate args checking, usage messages + +sub usage { + print <<"END_USAGE"; +Usage: $ME [OPTIONS] DIRECTORY-TO-CHECK + +$ME scans all .go files under the given DIRECTORY-TO-CHECK +(default: $Default_Dir), looking for lines of the form 'r.Handle(...)' +or 'r.HandleFunc(...)'. For each such line, we check for a preceding +swagger comment line and verify that the comment line matches the +declarations in the r.Handle() invocation. + +For example, the following would be a correctly-matching pair of lines: + + // swagger:operation GET /images/json compat getImages + r.Handle(VersionedPath("/images/json"), s.APIHandler(compat.GetImages)).Methods(http.MethodGet) + +...because http.MethodGet matches GET in the comment, the endpoint +is /images/json in both cases, the APIHandler() says "compat" so +that's the swagger tag, and the swagger operation name is the +same as the APIHandler but with a lower-case first letter. + +The following is an inconsistency as reported by this script: + +pkg/api/server/register_info.go: +- // swagger:operation GET /info libpod libpodGetInfo ++ // ................. ... ..... compat + r.Handle(VersionedPath("/info"), s.APIHandler(compat.GetInfo)).Methods(http.MethodGet) + +...because APIHandler() says 'compat' but the swagger comment +says 'libpod'. + +OPTIONS: + + --pedantic Compare operation names (the last part of swagger comment). + There are far too many of these inconsistencies to allow us + to enable this by default, but it still might be a useful + check in some circumstances. + + -v, --verbose show verbose progress indicators + -n, --dry-run make no actual changes + + --help display this message + --version display program name and version +END_USAGE + + exit; +} + +# Command-line options. Note that this operates directly on @ARGV ! +our $pedantic; +our $debug = 0; +our $force = 0; +our $verbose = 0; +our $NOT = ''; # print "blahing the blah$NOT\n" if $debug +sub handle_opts { + use Getopt::Long; + GetOptions( + 'pedantic' => \$pedantic, + + 'debug!' => \$debug, + 'dry-run|n!' => sub { $NOT = ' [NOT]' }, + 'force' => \$force, + 'verbose|v' => \$verbose, + + help => \&usage, + man => \&man, + version => sub { print "$ME version $VERSION\n"; exit 0 }, + ) or die "Try `$ME --help' for help\n"; +} + +# END boilerplate args checking, usage messages +############################################################################### + +############################## CODE BEGINS HERE ############################### + +my $exit_status = 0; + +# The term is "modulino". +__PACKAGE__->main() unless caller(); + +# Main code. +sub main { + # Note that we operate directly on @ARGV, not on function parameters. + # This is deliberate: it's because Getopt::Long only operates on @ARGV + # and there's no clean way to make it use @_. + handle_opts(); # will set package globals + + # Fetch command-line arguments. Barf if too many. + my $dir = shift(@ARGV) || $Default_Dir; + die "$ME: Too many arguments; try $ME --help\n" if @ARGV; + + # Find and act upon all matching files + find { wanted => sub { finder(@_) }, no_chdir => 1 }, $dir; + + exit $exit_status; +} + + +############ +# finder # File::Find action - looks for 'r.Handle' or 'r.HandleFunc' +############ +sub finder { + my $path = $File::Find::name; + return if $path =~ m|/\.|; # skip dotfiles + return unless $path =~ /\.go$/; # Only want .go files + + print $path, "\n" if $debug; + + # Read each .go file. Keep a running tally of all '// comment' lines; + # if we see a 'r.Handle()' or 'r.HandleFunc()' line, pass it + comments + # to analysis function. + open my $in, '<', $path + or die "$ME: Cannot read $path: $!\n"; + my @comments; + while (my $line = <$in>) { + if ($line =~ m!^\s*//!) { + push @comments, $line; + } + else { + # Not a comment line. If it's an r.Handle*() one, process it. + if ($line =~ m!^\s*r\.Handle(Func)?\(!) { + handle_handle($path, $line, @comments) + or $exit_status = 1; + } + + # Reset comments + @comments = (); + } + } + close $in; +} + + +################### +# handle_handle # Cross-check a 'r.Handle*' declaration against swagger +################### +# +# Returns false if swagger comment is inconsistent with function call, +# true if it matches or if there simply isn't a swagger comment. +# +sub handle_handle { + my $path = shift; # for error messages only + my $line = shift; # in: the r.Handle* line + my @comments = @_; # in: preceding comment lines + + # Preserve the original line, so we can show it in comments + my $line_orig = $line; + + # Strip off the 'r.Handle*(' and leading whitespace; preserve the latter + $line =~ s!^(\s*)r\.Handle(Func)?\(!! + or die "$ME: INTERNAL ERROR! Got '$line'!\n"; + my $indent = $1; + + # Some have VersionedPath, some don't. Doesn't seem to make a difference + # in terms of swagger, so let's just ignore it. + $line =~ s!^VersionedPath\(([^\)]+)\)!$1!; + $line =~ m!^"(/[^"]+)",! + or die "$ME: $path:$.: Cannot grok '$line'\n"; + my $endpoint = $1; + + # FIXME: in older code, '{name:..*}' meant 'nameOrID'. As of 2020-02 + # it looks like most of the '{name:..*}' entries are gone, except for one. +###FIXME-obsolete? $endpoint =~ s|\{name:\.\.\*\}|{nameOrID}|; + + # e.g. /auth, /containers/*/rename, /distribution, /monitor, /plugins + return 1 if $line =~ /\.UnsupportedHandler/; + + # + # Determine the HTTP METHOD (GET, POST, DELETE, HEAD) + # + my $method; + if ($line =~ /generic.VersionHandler/) { + $method = 'GET'; + } + elsif ($line =~ m!\.Methods\((.*)\)!) { + my $x = $1; + + if ($x =~ /Method(Post|Get|Delete|Head)/) { + $method = uc $1; + } + elsif ($x =~ /\"(HEAD|GET|POST)"/) { + $method = $1; + } + else { + die "$ME: $path:$.: Cannot grok $x\n"; + } + } + else { + warn "$ME: $path:$.: No Methods in '$line'\n"; + return 1; + } + + # + # Determine the SWAGGER TAG. Assume 'compat' unless we see libpod; but + # this can be overruled (see special case below) + # + my $tag = ($endpoint =~ /(libpod)/ ? $1 : 'compat'); + + # + # Determine the OPERATION. *** NOTE: This is mostly useless! *** + # In an ideal world the swagger comment would match actual function call; + # in reality there are over thirty mismatches. Use --pedantic to see. + # + my $operation = ''; + if ($line =~ /(generic|handlers|compat)\.(\w+)/) { + $operation = lcfirst $2; + if ($endpoint =~ m!/libpod/! && $operation !~ /^libpod/) { + $operation = 'libpod' . ucfirst $operation; + } + } + elsif ($line =~ /(libpod)\.(\w+)/) { + $operation = "$1$2"; + } + + # Special case: the following endpoints all get a custom tag + if ($endpoint =~ m!/(volumes|pods|manifests)/!) { + $tag = $1; + $operation =~ s/^libpod//; + $operation = lcfirst $operation; + } + + # Special case: anything related to 'events' gets a system tag + if ($endpoint =~ m!/events!) { + $tag = 'system'; + } + + # Special case: /changes is libpod even though it says compat + if ($endpoint =~ m!/changes!) { + $tag = 'libpod'; + } + + state $previous_path; # Previous path name, to avoid dups + + # + # Compare actual swagger comment to what we expect based on Handle call. + # + my $expect = " // swagger:operation $method $endpoint $tag $operation "; + my @actual = grep { /swagger:operation/ } @comments; + + return 1 if !@actual; # No swagger comment in file; oh well + + my $actual = $actual[0]; + + # By default, don't compare the operation: there are far too many + # mismatches here. + if (! $pedantic) { + $actual =~ s/\s+\S+\s*$//; + $expect =~ s/\s+\S+\s*$//; + } + + # (Ignore whitespace discrepancies) + (my $a_trimmed = $actual) =~ s/\s+/ /g; + + return 1 if $a_trimmed eq $expect; + + # Mismatch. Display it. Start with filename, if different from previous + print "\n"; + if (!$previous_path || $previous_path ne $path) { + print $path, ":\n"; + } + $previous_path = $path; + + # Show the actual line, prefixed with '-' ... + print "- $actual[0]"; + # ...then our generated ones, but use '...' as a way to ignore matches + print "+ $indent//"; + my @actual_split = split ' ', $actual; + my @expect_split = split ' ', $expect; + for my $i (1 .. $#actual_split) { + print " "; + if ($actual_split[$i] eq ($expect_split[$i]||'')) { + print "." x length($actual_split[$i]); + } + else { + # Show the difference. Use terminal highlights if available. + print "\e[1;37m" if -t *STDOUT; + print $expect_split[$i]; + print "\e[m" if -t *STDOUT; + } + } + print "\n"; + + # Show the r.Handle* code line itself + print " ", $line_orig; + + return; +} + +1; diff --git a/libpod/container.go b/libpod/container.go index c1deb95f9..a1848b96a 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -564,6 +564,11 @@ func (c *Container) MountLabel() string { return c.config.MountLabel } +// Systemd returns whether the container will be running in systemd mode +func (c *Container) Systemd() bool { + return c.config.Systemd +} + // User returns the user who the container is run as func (c *Container) User() string { return c.config.User diff --git a/libpod/container_internal.go b/libpod/container_internal.go index c930017a4..50bd9bc25 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -19,6 +19,7 @@ import ( "github.com/containers/libpod/pkg/hooks" "github.com/containers/libpod/pkg/hooks/exec" "github.com/containers/libpod/pkg/rootless" + "github.com/containers/libpod/pkg/util" "github.com/containers/storage" "github.com/containers/storage/pkg/archive" "github.com/containers/storage/pkg/mount" @@ -430,7 +431,22 @@ func (c *Container) setupStorage(ctx context.Context) error { c.config.IDMappings.UIDMap = containerInfo.UIDMap c.config.IDMappings.GIDMap = containerInfo.GIDMap - c.config.ProcessLabel = containerInfo.ProcessLabel + + processLabel := containerInfo.ProcessLabel + switch { + case c.ociRuntime.SupportsKVM(): + processLabel, err = util.SELinuxKVMLabel(processLabel) + if err != nil { + return err + } + case c.config.Systemd: + processLabel, err = util.SELinuxInitLabel(processLabel) + if err != nil { + return err + } + } + + c.config.ProcessLabel = processLabel c.config.MountLabel = containerInfo.MountLabel c.config.StaticDir = containerInfo.Dir c.state.RunDir = containerInfo.RunDir diff --git a/libpod/define/inspect.go b/libpod/define/ctr_inspect.go index b7cd13f82..b7cd13f82 100644 --- a/libpod/define/inspect.go +++ b/libpod/define/ctr_inspect.go diff --git a/libpod/define/info.go b/libpod/define/info.go index e9809c367..2516cad77 100644 --- a/libpod/define/info.go +++ b/libpod/define/info.go @@ -8,6 +8,7 @@ type Info struct { Host *HostInfo `json:"host"` Store *StoreInfo `json:"store"` Registries map[string]interface{} `json:"registries"` + Version Version `json:"version"` } //HostInfo describes the libpod host diff --git a/libpod/define/pod_inspect.go b/libpod/define/pod_inspect.go new file mode 100644 index 000000000..8558c149b --- /dev/null +++ b/libpod/define/pod_inspect.go @@ -0,0 +1,97 @@ +package define + +import ( + "net" + "time" + + "github.com/cri-o/ocicni/pkg/ocicni" +) + +// InspectPodData contains detailed information on a pod's configuration and +// state. It is used as the output of Inspect on pods. +type InspectPodData struct { + // ID is the ID of the pod. + ID string `json:"Id"` + // Name is the name of the pod. + Name string + // Namespace is the Libpod namespace the pod is placed in. + Namespace string `json:"Namespace,omitempty"` + // Created is the time when the pod was created. + Created time.Time + // Hostname is the hostname that the pod will set. + Hostname string + // Labels is a set of key-value labels that have been applied to the + // pod. + Labels map[string]string `json:"Labels,omitempty"` + // CreateCgroup is whether this pod will create its own CGroup to group + // containers under. + CreateCgroup bool + // CgroupParent is the parent of the pod's CGroup. + CgroupParent string `json:"CgroupParent,omitempty"` + // CgroupPath is the path to the pod's CGroup. + CgroupPath string `json:"CgroupPath,omitempty"` + // CreateInfra is whether this pod will create an infra container to + // share namespaces. + CreateInfra bool + // InfraContainerID is the ID of the pod's infra container, if one is + // present. + InfraContainerID string `json:"InfraContainerID,omitempty"` + // InfraConfig is the configuration of the infra container of the pod. + // Will only be set if CreateInfra is true. + InfraConfig *InspectPodInfraConfig `json:"InfraConfig,omitempty"` + // SharedNamespaces contains a list of namespaces that will be shared by + // containers within the pod. Can only be set if CreateInfra is true. + SharedNamespaces []string `json:"SharedNamespaces,omitempty"` + // NumContainers is the number of containers in the pod, including the + // infra container. + NumContainers uint + // Containers gives a brief summary of all containers in the pod and + // their current status. + Containers []InspectPodContainerInfo `json:"Containers,omitempty"` +} + +// InspectPodInfraConfig contains the configuration of the pod's infra +// container. +type InspectPodInfraConfig struct { + // PortBindings are ports that will be forwarded to the infra container + // and then shared with the pod. + PortBindings []ocicni.PortMapping + // HostNetwork is whether the infra container (and thus the whole pod) + // will use the host's network and not create a network namespace. + HostNetwork bool + // StaticIP is a static IPv4 that will be assigned to the infra + // container and then used by the pod. + StaticIP net.IP + // StaticMAC is a static MAC address that will be assigned to the infra + // container and then used by the pod. + StaticMAC net.HardwareAddr + // NoManageResolvConf indicates that the pod will not manage resolv.conf + // and instead each container will handle their own. + NoManageResolvConf bool + // DNSServer is a set of DNS Servers that will be used by the infra + // container's resolv.conf and shared with the remainder of the pod. + DNSServer []string + // DNSSearch is a set of DNS search domains that will be used by the + // infra container's resolv.conf and shared with the remainder of the + // pod. + DNSSearch []string + // DNSOption is a set of DNS options that will be used by the infra + // container's resolv.conf and shared with the remainder of the pod. + DNSOption []string + // NoManageHosts indicates that the pod will not manage /etc/hosts and + // instead each container will handle their own. + NoManageHosts bool + // HostAdd adds a number of hosts to the infra container's resolv.conf + // which will be shared with the rest of the pod. + HostAdd []string +} + +// InspectPodContainerInfo contains information on a container in a pod. +type InspectPodContainerInfo struct { + // ID is the ID of the container. + ID string `json:"Id"` + // Name is the name of the container. + Name string + // State is the current status of the container. + State string +} diff --git a/libpod/info.go b/libpod/info.go index 3cc767be6..d7ed5bb16 100644 --- a/libpod/info.go +++ b/libpod/info.go @@ -26,6 +26,11 @@ import ( // Info returns the store and host information func (r *Runtime) info() (*define.Info, error) { info := define.Info{} + versionInfo, err := define.GetVersion() + if err != nil { + return nil, errors.Wrapf(err, "error getting version info") + } + info.Version = versionInfo // get host information hostInfo, err := r.hostInfo() if err != nil { diff --git a/libpod/oci.go b/libpod/oci.go index 6adf42497..9991c5625 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -103,6 +103,9 @@ type OCIRuntime interface { // SupportsNoCgroups is whether the runtime supports running containers // without cgroups. SupportsNoCgroups() bool + // SupportsKVM os whether the OCI runtime supports running containers + // without KVM separation + SupportsKVM() bool // AttachSocketPath is the path to the socket to attach to a given // container. diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 18b438792..0113f7d8e 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -60,6 +60,7 @@ type ConmonOCIRuntime struct { noPivot bool reservePorts bool supportsJSON bool + supportsKVM bool supportsNoCgroups bool sdNotify bool } @@ -70,11 +71,25 @@ type ConmonOCIRuntime struct { // The first path that points to a valid executable will be used. // Deliberately private. Someone should not be able to construct this outside of // libpod. -func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtimeCfg *config.Config, supportsJSON, supportsNoCgroups bool) (OCIRuntime, error) { +func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtimeCfg *config.Config) (OCIRuntime, error) { if name == "" { return nil, errors.Wrapf(define.ErrInvalidArg, "the OCI runtime must be provided a non-empty name") } + // Make lookup tables for runtime support + supportsJSON := make(map[string]bool, len(runtimeCfg.Engine.RuntimeSupportsJSON)) + supportsNoCgroups := make(map[string]bool, len(runtimeCfg.Engine.RuntimeSupportsNoCgroups)) + supportsKVM := make(map[string]bool, len(runtimeCfg.Engine.RuntimeSupportsKVM)) + for _, r := range runtimeCfg.Engine.RuntimeSupportsJSON { + supportsJSON[r] = true + } + for _, r := range runtimeCfg.Engine.RuntimeSupportsNoCgroups { + supportsNoCgroups[r] = true + } + for _, r := range runtimeCfg.Engine.RuntimeSupportsKVM { + supportsKVM[r] = true + } + runtime := new(ConmonOCIRuntime) runtime.name = name runtime.conmonPath = conmonPath @@ -89,8 +104,9 @@ func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtime // TODO: probe OCI runtime for feature and enable automatically if // available. - runtime.supportsJSON = supportsJSON - runtime.supportsNoCgroups = supportsNoCgroups + runtime.supportsJSON = supportsJSON[name] + runtime.supportsNoCgroups = supportsNoCgroups[name] + runtime.supportsKVM = supportsKVM[name] foundPath := false for _, path := range paths { @@ -971,6 +987,12 @@ func (r *ConmonOCIRuntime) SupportsNoCgroups() bool { return r.supportsNoCgroups } +// SupportsKVM checks if the OCI runtime supports running containers +// without KVM separation +func (r *ConmonOCIRuntime) SupportsKVM() bool { + return r.supportsKVM +} + // AttachSocketPath is the path to a single container's attach socket. func (r *ConmonOCIRuntime) AttachSocketPath(ctr *Container) (string, error) { if ctr == nil { diff --git a/libpod/oci_conmon_unsupported.go b/libpod/oci_conmon_unsupported.go index 1f9d89ff6..309e0d417 100644 --- a/libpod/oci_conmon_unsupported.go +++ b/libpod/oci_conmon_unsupported.go @@ -17,7 +17,7 @@ type ConmonOCIRuntime struct { } // newConmonOCIRuntime is not supported on this OS. -func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtimeCfg *config.Config, supportsJSON, supportsNoCgroups bool) (OCIRuntime, error) { +func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtimeCfg *config.Config) (OCIRuntime, error) { return nil, define.ErrNotImplemented } diff --git a/libpod/oci_missing.go b/libpod/oci_missing.go index 5284fb4b7..172805b0d 100644 --- a/libpod/oci_missing.go +++ b/libpod/oci_missing.go @@ -168,6 +168,12 @@ func (r *MissingRuntime) SupportsNoCgroups() bool { return false } +// SupportsKVM checks if the OCI runtime supports running containers +// without KVM separation +func (r *MissingRuntime) SupportsKVM() bool { + return false +} + // AttachSocketPath does not work as there is no runtime to attach to. // (Theoretically we could follow ExitFilePath but there is no guarantee the // container is running and thus has an attach socket...) diff --git a/libpod/runtime.go b/libpod/runtime.go index a6032ad23..3b8f9e057 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -359,25 +359,13 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { } } - // Make lookup tables for runtime support - supportsJSON := make(map[string]bool) - supportsNoCgroups := make(map[string]bool) - for _, r := range runtime.config.Engine.RuntimeSupportsJSON { - supportsJSON[r] = true - } - for _, r := range runtime.config.Engine.RuntimeSupportsNoCgroups { - supportsNoCgroups[r] = true - } - // Get us at least one working OCI runtime. runtime.ociRuntimes = make(map[string]OCIRuntime) // Initialize remaining OCI runtimes for name, paths := range runtime.config.Engine.OCIRuntimes { - json := supportsJSON[name] - nocgroups := supportsNoCgroups[name] - ociRuntime, err := newConmonOCIRuntime(name, paths, runtime.conmonPath, runtime.config, json, nocgroups) + ociRuntime, err := newConmonOCIRuntime(name, paths, runtime.conmonPath, runtime.config) if err != nil { // Don't fatally error. // This will allow us to ship configs including optional @@ -397,10 +385,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { if strings.HasPrefix(runtime.config.Engine.OCIRuntime, "/") { name := filepath.Base(runtime.config.Engine.OCIRuntime) - json := supportsJSON[name] - nocgroups := supportsNoCgroups[name] - - ociRuntime, err := newConmonOCIRuntime(name, []string{runtime.config.Engine.OCIRuntime}, runtime.conmonPath, runtime.config, json, nocgroups) + ociRuntime, err := newConmonOCIRuntime(name, []string{runtime.config.Engine.OCIRuntime}, runtime.conmonPath, runtime.config) if err != nil { return err } @@ -813,3 +798,7 @@ func (r *Runtime) mergeDBConfig(dbConfig *DBConfig) error { } return nil } + +func (r *Runtime) EnableLabeling() bool { + return r.config.Containers.EnableLabeling +} diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 207ac6477..9d3e69d56 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -887,8 +887,9 @@ func (r *Runtime) PruneContainers(filterFuncs []ContainerFilter) (map[string]int continue } err = r.RemoveContainer(context.Background(), ctr, false, false) - pruneErrors[ctr.ID()] = err if err != nil { + pruneErrors[ctr.ID()] = err + } else { prunedContainers[ctr.ID()] = size } } diff --git a/pkg/api/handlers/compat/containers_prune.go b/pkg/api/handlers/compat/containers_prune.go index a56c3903d..b4e98ac1f 100644 --- a/pkg/api/handlers/compat/containers_prune.go +++ b/pkg/api/handlers/compat/containers_prune.go @@ -4,8 +4,9 @@ import ( "net/http" "github.com/containers/libpod/libpod" - "github.com/containers/libpod/pkg/api/handlers" + lpfilters "github.com/containers/libpod/libpod/filters" "github.com/containers/libpod/pkg/api/handlers/utils" + "github.com/containers/libpod/pkg/domain/entities" "github.com/docker/docker/api/types" "github.com/gorilla/schema" "github.com/pkg/errors" @@ -15,6 +16,7 @@ func PruneContainers(w http.ResponseWriter, r *http.Request) { var ( delContainers []string space int64 + filterFuncs []libpod.ContainerFilter ) runtime := r.Context().Value("runtime").(*libpod.Runtime) decoder := r.Context().Value("decoder").(*schema.Decoder) @@ -26,11 +28,15 @@ func PruneContainers(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String())) return } - - filterFuncs, err := utils.GenerateFilterFuncsFromMap(runtime, query.Filters) - if err != nil { - utils.InternalServerError(w, err) - return + for k, v := range query.Filters { + for _, val := range v { + generatedFunc, err := lpfilters.GenerateContainerFilterFuncs(k, val, runtime) + if err != nil { + utils.InternalServerError(w, err) + return + } + filterFuncs = append(filterFuncs, generatedFunc) + } } prunedContainers, pruneErrors, err := runtime.PruneContainers(filterFuncs) if err != nil { @@ -40,14 +46,11 @@ func PruneContainers(w http.ResponseWriter, r *http.Request) { // Libpod response differs if utils.IsLibpodRequest(r) { - var response []handlers.LibpodContainersPruneReport - for ctrID, size := range prunedContainers { - response = append(response, handlers.LibpodContainersPruneReport{ID: ctrID, SpaceReclaimed: size}) - } - for ctrID, err := range pruneErrors { - response = append(response, handlers.LibpodContainersPruneReport{ID: ctrID, PruneError: err.Error()}) + report := &entities.ContainerPruneReport{ + Err: pruneErrors, + ID: prunedContainers, } - utils.WriteResponse(w, http.StatusOK, response) + utils.WriteResponse(w, http.StatusOK, report) return } for ctrID, size := range prunedContainers { diff --git a/pkg/api/handlers/libpod/volumes.go b/pkg/api/handlers/libpod/volumes.go index 5a6fc021e..18c561a0d 100644 --- a/pkg/api/handlers/libpod/volumes.go +++ b/pkg/api/handlers/libpod/volumes.go @@ -4,12 +4,12 @@ import ( "encoding/json" "net/http" - "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/api/handlers/utils" "github.com/containers/libpod/pkg/domain/entities" "github.com/containers/libpod/pkg/domain/filters" + "github.com/containers/libpod/pkg/domain/infra/abi/parse" "github.com/gorilla/schema" "github.com/pkg/errors" ) @@ -46,7 +46,7 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) { volumeOptions = append(volumeOptions, libpod.WithVolumeLabels(input.Label)) } if len(input.Options) > 0 { - parsedOptions, err := shared.ParseVolumeOptions(input.Options) + parsedOptions, err := parse.ParseVolumeOptions(input.Options) if err != nil { utils.InternalServerError(w, err) return diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go index bbe4cee3c..d1107f67c 100644 --- a/pkg/api/handlers/utils/containers.go +++ b/pkg/api/handlers/utils/containers.go @@ -6,9 +6,10 @@ import ( "time" "github.com/containers/libpod/cmd/podman/shared" + createconfig "github.com/containers/libpod/pkg/spec" + "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" - createconfig "github.com/containers/libpod/pkg/spec" "github.com/gorilla/schema" "github.com/pkg/errors" ) @@ -68,24 +69,6 @@ func WaitContainer(w http.ResponseWriter, r *http.Request) (int32, error) { return con.WaitForConditionWithInterval(interval, condition) } -// GenerateFilterFuncsFromMap is used to generate un-executed functions that can be used to filter -// containers. It is specifically designed for the RESTFUL API input. -func GenerateFilterFuncsFromMap(r *libpod.Runtime, filters map[string][]string) ([]libpod.ContainerFilter, error) { - var ( - filterFuncs []libpod.ContainerFilter - ) - for k, v := range filters { - for _, val := range v { - f, err := shared.GenerateContainerFilterFuncs(k, val, r) - if err != nil { - return filterFuncs, err - } - filterFuncs = append(filterFuncs, f) - } - } - return filterFuncs, nil -} - func CreateContainer(ctx context.Context, w http.ResponseWriter, runtime *libpod.Runtime, cc *createconfig.CreateConfig) { var pod *libpod.Pod ctr, err := shared.CreateContainerFromCreateConfig(runtime, cc, ctx, pod) diff --git a/pkg/api/handlers/utils/pods.go b/pkg/api/handlers/utils/pods.go index d47053eda..fb795fa6a 100644 --- a/pkg/api/handlers/utils/pods.go +++ b/pkg/api/handlers/utils/pods.go @@ -1,20 +1,19 @@ package utils import ( - "fmt" "net/http" - "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" + lpfilters "github.com/containers/libpod/libpod/filters" "github.com/containers/libpod/pkg/domain/entities" "github.com/gorilla/schema" ) func GetPods(w http.ResponseWriter, r *http.Request) ([]*entities.ListPodsReport, error) { var ( - lps []*entities.ListPodsReport - pods []*libpod.Pod - podErr error + lps []*entities.ListPodsReport + pods []*libpod.Pod + filters []libpod.PodFilter ) runtime := r.Context().Value("runtime").(*libpod.Runtime) decoder := r.Context().Value("decoder").(*schema.Decoder) @@ -28,28 +27,24 @@ func GetPods(w http.ResponseWriter, r *http.Request) ([]*entities.ListPodsReport if err := decoder.Decode(&query, r.URL.Query()); err != nil { return nil, err } - var filters = []string{} if _, found := r.URL.Query()["digests"]; found && query.Digests { UnSupportedParameter("digests") } - if len(query.Filters) > 0 { - for k, v := range query.Filters { - for _, val := range v { - filters = append(filters, fmt.Sprintf("%s=%s", k, val)) + for k, v := range query.Filters { + for _, filter := range v { + f, err := lpfilters.GeneratePodFilterFunc(k, filter) + if err != nil { + return nil, err } + filters = append(filters, f) } - filterFuncs, err := shared.GenerateFilterFunction(runtime, filters) - if err != nil { - return nil, err - } - pods, podErr = shared.FilterAllPodsWithFilterFunc(runtime, filterFuncs...) - } else { - pods, podErr = runtime.GetAllPods() } - if podErr != nil { - return nil, podErr + pods, err := runtime.Pods(filters...) + if err != nil { + return nil, err } + for _, pod := range pods { status, err := pod.GetPodStatus() if err != nil { diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go index 8b9a9e312..378d1e06c 100644 --- a/pkg/api/server/register_containers.go +++ b/pkg/api/server/register_containers.go @@ -955,7 +955,7 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // "$ref": "#/responses/NoSuchContainer" // 500: // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/pause"), s.APIHandler(compat.PauseContainer)).Methods(http.MethodPost) + r.HandleFunc(VersionedPath("/libpod/containers/{name}/pause"), s.APIHandler(compat.PauseContainer)).Methods(http.MethodPost) // swagger:operation POST /libpod/containers/{name}/restart libpod libpodRestartContainer // --- // tags: @@ -1282,7 +1282,7 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name}/export"), s.APIHandler(compat.ExportContainer)).Methods(http.MethodGet) - // swagger:operation GET /libpod/containers/{name}/checkout libpod libpodCheckpointContainer + // swagger:operation POST /libpod/containers/{name}/checkpoint libpod libpodCheckpointContainer // --- // tags: // - containers @@ -1323,7 +1323,7 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name}/checkpoint"), s.APIHandler(libpod.Checkpoint)).Methods(http.MethodPost) - // swagger:operation GET /libpod/containers/{name} restore libpod libpodRestoreContainer + // swagger:operation POST /libpod/containers/{name}/restore libpod libpodRestoreContainer // --- // tags: // - containers @@ -1407,9 +1407,9 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // $ref: "#/responses/NoSuchContainer" // 500: // $ref: "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/{name}/changes"), s.APIHandler(compat.Changes)) - r.HandleFunc("/containers/{name}/changes", s.APIHandler(compat.Changes)) - r.HandleFunc(VersionedPath("/libpod/containers/{name}/changes"), s.APIHandler(compat.Changes)) + r.HandleFunc(VersionedPath("/containers/{name}/changes"), s.APIHandler(compat.Changes)).Methods(http.MethodGet) + r.HandleFunc("/containers/{name}/changes", s.APIHandler(compat.Changes)).Methods(http.MethodGet) + r.HandleFunc(VersionedPath("/libpod/containers/{name}/changes"), s.APIHandler(compat.Changes)).Methods(http.MethodGet) // swagger:operation POST /libpod/containers/{name}/init libpod libpodInitContainer // --- // tags: diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 7dd887037..6cc6f0cfa 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -1154,7 +1154,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // $ref: "#/responses/NoSuchContainer" // 500: // $ref: "#/responses/InternalError" - r.HandleFunc(VersionedPath("/libpod/images/{name}/changes"), s.APIHandler(compat.Changes)) + r.HandleFunc(VersionedPath("/libpod/images/{name}/changes"), s.APIHandler(compat.Changes)).Methods(http.MethodGet) return nil } diff --git a/pkg/autoupdate/autoupdate.go b/pkg/autoupdate/autoupdate.go index 7c243eb00..78d5ac474 100644 --- a/pkg/autoupdate/autoupdate.go +++ b/pkg/autoupdate/autoupdate.go @@ -201,18 +201,25 @@ func imageContainersMap(runtime *libpod.Runtime) (map[string][]*libpod.Container if state != define.ContainerStateRunning { continue } + // Only update containers with the specific label/policy set. labels := ctr.Labels() - if value, exists := labels[Label]; exists { - policy, err := LookupPolicy(value) - if err != nil { - errors = append(errors, err) - continue - } - if policy != PolicyNewImage { - continue - } + value, exists := labels[Label] + if !exists { + continue } + + policy, err := LookupPolicy(value) + if err != nil { + errors = append(errors, err) + continue + } + + // Skip non-image labels (could be explicitly disabled). + if policy != PolicyNewImage { + continue + } + // Now we know that `ctr` is configured for auto updates. id, _ := ctr.Image() imageMap[id] = append(imageMap[id], allContainers[i]) diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go index 963f0ec57..e74a256c7 100644 --- a/pkg/bindings/containers/containers.go +++ b/pkg/bindings/containers/containers.go @@ -60,10 +60,8 @@ func List(ctx context.Context, filters map[string][]string, all *bool, last *int // used for more granular selection of containers. The main error returned indicates if there were runtime // errors like finding containers. Errors specific to the removal of a container are in the PruneContainerResponse // structure. -func Prune(ctx context.Context, filters map[string][]string) ([]string, error) { - var ( - pruneResponse []string - ) +func Prune(ctx context.Context, filters map[string][]string) (*entities.ContainerPruneReport, error) { + var reports *entities.ContainerPruneReport conn, err := bindings.GetClient(ctx) if err != nil { return nil, err @@ -78,9 +76,9 @@ func Prune(ctx context.Context, filters map[string][]string) ([]string, error) { } response, err := conn.DoRequest(nil, http.MethodPost, "/containers/prune", params) if err != nil { - return pruneResponse, err + return nil, err } - return pruneResponse, response.Process(pruneResponse) + return reports, response.Process(&reports) } // Remove removes a container from local storage. The force bool designates diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go index 0b1b9ecdd..e288dc368 100644 --- a/pkg/bindings/test/containers_test.go +++ b/pkg/bindings/test/containers_test.go @@ -531,4 +531,69 @@ var _ = Describe("Podman containers ", func() { Expect(err).ToNot(BeNil()) }) + It("podman prune stoped containers", func() { + // Start and stop a container to enter in exited state. + var name = "top" + _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) + Expect(err).To(BeNil()) + err = containers.Stop(bt.conn, name, nil) + Expect(err).To(BeNil()) + + // Prune container should return no errors and one pruned container ID. + pruneResponse, err := containers.Prune(bt.conn, nil) + Expect(err).To(BeNil()) + Expect(len(pruneResponse.Err)).To(Equal(0)) + Expect(len(pruneResponse.ID)).To(Equal(1)) + }) + + It("podman prune stoped containers with filters", func() { + // Start and stop a container to enter in exited state. + var name = "top" + _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) + Expect(err).To(BeNil()) + err = containers.Stop(bt.conn, name, nil) + Expect(err).To(BeNil()) + + // Invalid filter keys should return error. + filtersIncorrect := map[string][]string{ + "status": {"dummy"}, + } + pruneResponse, err := containers.Prune(bt.conn, filtersIncorrect) + Expect(err).ToNot(BeNil()) + + // Mismatched filter params no container should be pruned. + filtersIncorrect = map[string][]string{ + "name": {"r"}, + } + pruneResponse, err = containers.Prune(bt.conn, filtersIncorrect) + Expect(err).To(BeNil()) + Expect(len(pruneResponse.Err)).To(Equal(0)) + Expect(len(pruneResponse.ID)).To(Equal(0)) + + // Valid filter params container should be pruned now. + filters := map[string][]string{ + "name": {"top"}, + } + pruneResponse, err = containers.Prune(bt.conn, filters) + Expect(err).To(BeNil()) + Expect(len(pruneResponse.Err)).To(Equal(0)) + Expect(len(pruneResponse.ID)).To(Equal(1)) + }) + + It("podman prune running containers", func() { + // Start the container. + var name = "top" + _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) + Expect(err).To(BeNil()) + + // Check if the container is running. + data, err := containers.Inspect(bt.conn, name, nil) + Expect(err).To(BeNil()) + Expect(data.State.Status).To(Equal("running")) + + // Prune. Should return no error no prune response ID. + pruneResponse, err := containers.Prune(bt.conn, nil) + Expect(err).To(BeNil()) + Expect(len(pruneResponse.ID)).To(Equal(0)) + }) }) diff --git a/pkg/domain/entities/container_ps.go b/pkg/domain/entities/container_ps.go index ceafecebc..33f5d0500 100644 --- a/pkg/domain/entities/container_ps.go +++ b/pkg/domain/entities/container_ps.go @@ -4,8 +4,8 @@ import ( "sort" "strings" - "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" + "github.com/containers/libpod/pkg/ps/define" "github.com/cri-o/ocicni/pkg/ocicni" "github.com/pkg/errors" ) @@ -48,7 +48,7 @@ type ListContainer struct { // Port mappings Ports []ocicni.PortMapping // Size of the container rootfs. Requires the size boolean to be true - Size *shared.ContainerSize + Size *define.ContainerSize // Time when container started StartedAt int64 // State of container diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go index f21af9ce4..52327a905 100644 --- a/pkg/domain/entities/containers.go +++ b/pkg/domain/entities/containers.go @@ -2,6 +2,7 @@ package entities import ( "io" + "net/url" "os" "time" @@ -260,7 +261,7 @@ type ContainerRunOptions struct { } // ContainerRunReport describes the results of running -//a container +// a container type ContainerRunReport struct { ExitCode int Id string @@ -327,3 +328,16 @@ type ContainerUnmountReport struct { Err error Id string } + +// ContainerPruneOptions describes the options needed +// to prune a container from the CLI +type ContainerPruneOptions struct { + Filters url.Values `json:"filters" schema:"filters"` +} + +// ContainerPruneReport describes the results after pruning the +// stopped containers. +type ContainerPruneReport struct { + ID map[string]int64 + Err map[string]error +} diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go index 5fdb9a8a6..c3092a98a 100644 --- a/pkg/domain/entities/engine_container.go +++ b/pkg/domain/entities/engine_container.go @@ -13,6 +13,7 @@ type ContainerEngine interface { ContainerAttach(ctx context.Context, nameOrId string, options AttachOptions) error ContainerCheckpoint(ctx context.Context, namesOrIds []string, options CheckpointOptions) ([]*CheckpointReport, error) ContainerCleanup(ctx context.Context, namesOrIds []string, options ContainerCleanupOptions) ([]*ContainerCleanupReport, error) + ContainerPrune(ctx context.Context, options ContainerPruneOptions) (*ContainerPruneReport, error) ContainerCommit(ctx context.Context, nameOrId string, options CommitOptions) (*CommitReport, error) ContainerCreate(ctx context.Context, s *specgen.SpecGenerator) (*ContainerCreateReport, error) ContainerDiff(ctx context.Context, nameOrId string, options DiffOptions) (*DiffReport, error) diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index f464df3ac..4279fb756 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -11,6 +11,8 @@ import ( "strings" "sync" + lpfilters "github.com/containers/libpod/libpod/filters" + "github.com/containers/buildah" "github.com/containers/common/pkg/config" "github.com/containers/image/v5/manifest" @@ -173,6 +175,28 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin return reports, nil } +func (ic *ContainerEngine) ContainerPrune(ctx context.Context, options entities.ContainerPruneOptions) (*entities.ContainerPruneReport, error) { + var filterFuncs []libpod.ContainerFilter + for k, v := range options.Filters { + for _, val := range v { + generatedFunc, err := lpfilters.GenerateContainerFilterFuncs(k, val, ic.Libpod) + if err != nil { + return nil, err + } + filterFuncs = append(filterFuncs, generatedFunc) + } + } + prunedContainers, pruneErrors, err := ic.Libpod.PruneContainers(filterFuncs) + if err != nil { + return nil, err + } + report := entities.ContainerPruneReport{ + ID: prunedContainers, + Err: pruneErrors, + } + return &report, nil +} + func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, options entities.KillOptions) ([]*entities.KillReport, error) { var ( reports []*entities.KillReport diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go index 9cf374e2e..6b0ac4852 100644 --- a/pkg/domain/infra/runtime_libpod.go +++ b/pkg/domain/infra/runtime_libpod.go @@ -160,7 +160,7 @@ func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpo } if fs.Changed("runtime") { - options = append(options, libpod.WithOCIRuntime(cfg.RuntimePath)) + options = append(options, libpod.WithOCIRuntime(cfg.Engine.OCIRuntime)) } if fs.Changed("conmon") { diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index 05b62efcf..679bb371b 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -146,6 +146,10 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, return reports, nil } +func (ic *ContainerEngine) ContainerPrune(ctx context.Context, options entities.ContainerPruneOptions) (*entities.ContainerPruneReport, error) { + return containers.Prune(ic.ClientCxt, options.Filters) +} + func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.InspectOptions) ([]*entities.ContainerInspectReport, error) { var ( reports []*entities.ContainerInspectReport diff --git a/pkg/ps/define/types.go b/pkg/ps/define/types.go new file mode 100644 index 000000000..878653c3a --- /dev/null +++ b/pkg/ps/define/types.go @@ -0,0 +1,8 @@ +package define + +// ContainerSize holds the size of the container's root filesystem and top +// read-write layer. +type ContainerSize struct { + RootFsSize int64 `json:"rootFsSize"` + RwSize int64 `json:"rwSize"` +} diff --git a/pkg/ps/ps.go b/pkg/ps/ps.go index 58fcc2c21..8b62fc307 100644 --- a/pkg/ps/ps.go +++ b/pkg/ps/ps.go @@ -1,16 +1,19 @@ package ps import ( + "os" "path/filepath" + "regexp" "sort" "strconv" + "strings" "time" - "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" lpfilters "github.com/containers/libpod/libpod/filters" "github.com/containers/libpod/pkg/domain/entities" + psdefine "github.com/containers/libpod/pkg/ps/define" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -80,7 +83,7 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities exitCode int32 exited bool pid int - size *shared.ContainerSize + size *psdefine.ContainerSize startedTime time.Time exitedTime time.Time cgroup, ipc, mnt, net, pidns, user, uts string @@ -116,16 +119,16 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities return errors.Wrapf(err, "unable to obtain container pid") } ctrPID := strconv.Itoa(pid) - cgroup, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "cgroup")) - ipc, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "ipc")) - mnt, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "mnt")) - net, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "net")) - pidns, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "pid")) - user, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "user")) - uts, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "uts")) + cgroup, _ = getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "cgroup")) + ipc, _ = getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "ipc")) + mnt, _ = getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "mnt")) + net, _ = getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "net")) + pidns, _ = getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "pid")) + user, _ = getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "user")) + uts, _ = getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "uts")) } if opts.Size { - size = new(shared.ContainerSize) + size = new(psdefine.ContainerSize) rootFsSize, err := c.RootFsSize() if err != nil { @@ -187,3 +190,18 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities } return ps, nil } + +func getNamespaceInfo(path string) (string, error) { + val, err := os.Readlink(path) + if err != nil { + return "", errors.Wrapf(err, "error getting info from %q", path) + } + return getStrFromSquareBrackets(val), nil +} + +// getStrFromSquareBrackets gets the string inside [] from a string. +func getStrFromSquareBrackets(cmd string) string { + reg := regexp.MustCompile(`.*\[|\].*`) + arr := strings.Split(reg.ReplaceAllLiteralString(cmd, ""), ",") + return strings.Join(arr, ",") +} diff --git a/pkg/specgen/container_validate.go b/pkg/specgen/container_validate.go index aad14ddcb..9152e7ee7 100644 --- a/pkg/specgen/container_validate.go +++ b/pkg/specgen/container_validate.go @@ -68,18 +68,6 @@ func (s *SpecGenerator) Validate() error { if len(s.CapAdd) > 0 && s.Privileged { return exclusiveOptions("CapAdd", "privileged") } - // selinuxprocesslabel and privileged are exclusive - if len(s.SelinuxProcessLabel) > 0 && s.Privileged { - return exclusiveOptions("SelinuxProcessLabel", "privileged") - } - // selinuxmounmtlabel and privileged are exclusive - if len(s.SelinuxMountLabel) > 0 && s.Privileged { - return exclusiveOptions("SelinuxMountLabel", "privileged") - } - // selinuxopts and privileged are exclusive - if len(s.SelinuxOpts) > 0 && s.Privileged { - return exclusiveOptions("SelinuxOpts", "privileged") - } // apparmor and privileged are exclusive if len(s.ApparmorProfile) > 0 && s.Privileged { return exclusiveOptions("AppArmorProfile", "privileged") diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go index 78c77fec1..edd54847d 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -113,6 +113,14 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat if err := finishThrottleDevices(s); err != nil { return err } + // Unless already set via the CLI, check if we need to disable process + // labels or set the defaults. + if len(s.SelinuxOpts) == 0 { + if err := s.SetLabelOpts(r, s.PidNS, s.IpcNS); err != nil { + return err + } + } + return nil } diff --git a/pkg/specgen/security.go b/pkg/specgen/security.go index 158e4a7b3..6f835eae4 100644 --- a/pkg/specgen/security.go +++ b/pkg/specgen/security.go @@ -1,32 +1,26 @@ package specgen -// ToCreateOptions convert the SecurityConfig to a slice of container create -// options. -/* -func (c *SecurityConfig) ToCreateOptions() ([]libpod.CtrCreateOption, error) { - options := make([]libpod.CtrCreateOption, 0) - options = append(options, libpod.WithSecLabels(c.LabelOpts)) - options = append(options, libpod.WithPrivileged(c.Privileged)) - return options, nil -} -*/ +import ( + "github.com/containers/libpod/libpod" + "github.com/opencontainers/selinux/go-selinux/label" + "github.com/pkg/errors" +) // SetLabelOpts sets the label options of the SecurityConfig according to the // input. -/* -func (c *SecurityConfig) SetLabelOpts(runtime *libpod.Runtime, pidConfig *PidConfig, ipcConfig *IpcConfig) error { - if c.Privileged { - c.LabelOpts = label.DisableSecOpt() +func (s *SpecGenerator) SetLabelOpts(runtime *libpod.Runtime, pidConfig Namespace, ipcConfig Namespace) error { + if !runtime.EnableLabeling() || s.Privileged { + s.SelinuxOpts = label.DisableSecOpt() return nil } var labelOpts []string - if pidConfig.PidMode.IsHost() { + if pidConfig.IsHost() { labelOpts = append(labelOpts, label.DisableSecOpt()...) - } else if pidConfig.PidMode.IsContainer() { - ctr, err := runtime.LookupContainer(pidConfig.PidMode.Container()) + } else if pidConfig.IsContainer() { + ctr, err := runtime.LookupContainer(pidConfig.Value) if err != nil { - return errors.Wrapf(err, "container %q not found", pidConfig.PidMode.Container()) + return errors.Wrapf(err, "container %q not found", pidConfig.Value) } secopts, err := label.DupSecOpt(ctr.ProcessLabel()) if err != nil { @@ -35,12 +29,12 @@ func (c *SecurityConfig) SetLabelOpts(runtime *libpod.Runtime, pidConfig *PidCon labelOpts = append(labelOpts, secopts...) } - if ipcConfig.IpcMode.IsHost() { + if ipcConfig.IsHost() { labelOpts = append(labelOpts, label.DisableSecOpt()...) - } else if ipcConfig.IpcMode.IsContainer() { - ctr, err := runtime.LookupContainer(ipcConfig.IpcMode.Container()) + } else if ipcConfig.IsContainer() { + ctr, err := runtime.LookupContainer(ipcConfig.Value) if err != nil { - return errors.Wrapf(err, "container %q not found", ipcConfig.IpcMode.Container()) + return errors.Wrapf(err, "container %q not found", ipcConfig.Value) } secopts, err := label.DupSecOpt(ctr.ProcessLabel()) if err != nil { @@ -49,13 +43,7 @@ func (c *SecurityConfig) SetLabelOpts(runtime *libpod.Runtime, pidConfig *PidCon labelOpts = append(labelOpts, secopts...) } - c.LabelOpts = append(c.LabelOpts, labelOpts...) - return nil -} -*/ - -// SetSecurityOpts the the security options (labels, apparmor, seccomp, etc.). -func SetSecurityOpts(securityOpts []string) error { + s.SelinuxOpts = append(s.SelinuxOpts, labelOpts...) return nil } diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index 8482ef2c9..1a05733f9 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -228,14 +228,6 @@ type ContainerSecurityConfig struct { // If SELinux is enabled and this is not specified, a label will be // automatically generated if not specified. // Optional. - SelinuxProcessLabel string `json:"selinux_process_label,omitempty"` - // SelinuxMountLabel is the mount label the container will use. - // If SELinux is enabled and this is not specified, a label will be - // automatically generated if not specified. - // Optional. - SelinuxMountLabel string `json:"selinux_mount_label,omitempty"` - // SelinuxOpts are options for configuring SELinux. - // Optional. SelinuxOpts []string `json:"selinux_opts,omitempty"` // ApparmorProfile is the name of the Apparmor profile the container // will use. diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 1051ed311..babf7dfc9 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -14,7 +14,6 @@ import ( "github.com/BurntSushi/toml" "github.com/containers/image/v5/types" - "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/pkg/errorhandling" "github.com/containers/libpod/pkg/namespaces" "github.com/containers/libpod/pkg/rootless" @@ -22,9 +21,9 @@ import ( "github.com/containers/storage" "github.com/containers/storage/pkg/idtools" v1 "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/opencontainers/selinux/go-selinux" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "github.com/spf13/pflag" "golang.org/x/crypto/ssh/terminal" ) @@ -515,37 +514,6 @@ func ParseInputTime(inputTime string) (time.Time, error) { return time.Now().Add(-duration), nil } -// GetGlobalOpts checks all global flags and generates the command string -// FIXME: Port input to config.Config -// TODO: Is there a "better" way to reverse values to flags? This seems brittle. -func GetGlobalOpts(c *cliconfig.RunlabelValues) string { - globalFlags := map[string]bool{ - "cgroup-manager": true, "cni-config-dir": true, "conmon": true, "default-mounts-file": true, - "hooks-dir": true, "namespace": true, "root": true, "runroot": true, - "runtime": true, "storage-driver": true, "storage-opt": true, "syslog": true, - "trace": true, "network-cmd-path": true, "config": true, "cpu-profile": true, - "log-level": true, "tmpdir": true} - const stringSliceType string = "stringSlice" - - var optsCommand []string - c.PodmanCommand.Command.Flags().VisitAll(func(f *pflag.Flag) { - if !f.Changed { - return - } - if _, exist := globalFlags[f.Name]; exist { - if f.Value.Type() == stringSliceType { - flagValue := strings.TrimSuffix(strings.TrimPrefix(f.Value.String(), "["), "]") - for _, value := range strings.Split(flagValue, ",") { - optsCommand = append(optsCommand, fmt.Sprintf("--%s %s", f.Name, value)) - } - } else { - optsCommand = append(optsCommand, fmt.Sprintf("--%s %s", f.Name, f.Value.String())) - } - } - }) - return strings.Join(optsCommand, " ") -} - // OpenExclusiveFile opens a file for writing and ensure it doesn't already exist func OpenExclusiveFile(path string) (*os.File, error) { baseDir := filepath.Dir(path) @@ -666,3 +634,38 @@ func ValidateSysctls(strSlice []string) (map[string]string, error) { } return sysctl, nil } + +// SELinuxKVMLabel returns labels for running kvm isolated containers +func SELinuxKVMLabel(cLabel string) (string, error) { + if cLabel == "" { + // selinux is disabled + return "", nil + } + processLabel, _ := selinux.KVMContainerLabels() + selinux.ReleaseLabel(processLabel) + return swapSELinuxLabel(cLabel, processLabel) +} + +// SELinuxInitLabel returns labels for running systemd based containers +func SELinuxInitLabel(cLabel string) (string, error) { + if cLabel == "" { + // selinux is disabled + return "", nil + } + processLabel, _ := selinux.InitContainerLabels() + selinux.ReleaseLabel(processLabel) + return swapSELinuxLabel(cLabel, processLabel) +} + +func swapSELinuxLabel(cLabel, processLabel string) (string, error) { + dcon, err := selinux.NewContext(cLabel) + if err != nil { + return "", err + } + scon, err := selinux.NewContext(processLabel) + if err != nil { + return "", err + } + dcon["type"] = scon["type"] + return dcon.Get(), nil +} diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go index b65db2722..bddbee876 100644 --- a/vendor/github.com/containers/common/pkg/config/config.go +++ b/vendor/github.com/containers/common/pkg/config/config.go @@ -87,6 +87,9 @@ type ContainersConfig struct { // Default way to create a cgroup namespace for the container CgroupNS string `toml:"cgroupns"` + // Default cgroup configuration + Cgroups string `toml:"cgroups"` + // Capabilities to add to all containers. DefaultCapabilities []string `toml:"default_capabilities"` @@ -271,6 +274,10 @@ type EngineConfig struct { // running containers without CGroups. RuntimeSupportsNoCgroups []string `toml:"runtime_supports_nocgroupv2"` + // RuntimeSupportsKVM is a list of OCI runtimes that support + // KVM separation for conatainers. + RuntimeSupportsKVM []string `toml:"runtime_supports_kvm"` + // 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 the parsed // configuration file. If not, the corresponding option might be diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf index 067be429e..a029aedeb 100644 --- a/vendor/github.com/containers/common/pkg/config/containers.conf +++ b/vendor/github.com/containers/common/pkg/config/containers.conf @@ -47,6 +47,15 @@ # # cgroupns = "private" +# Control container cgroup configuration +# Determines whether the container will create CGroups. +# Options are: +# `enabled` Enable cgroup support within container +# `disabled` Disable cgroup support, will inherit cgroups from parent +# `no-conmon` Container engine runs run without conmon +# +# cgroups = "enabled" + # List of default capabilities for containers. If it is empty or commented out, # the default capabilities defined in the container engine will be added. # @@ -347,6 +356,14 @@ # # runtime_supports_json = ["crun", "runc", "kata"] +# List of the OCI runtimes that supports running containers without cgroups. +# +# runtime_supports_nocgroups = ["crun"] + +# List of the OCI runtimes that supports running containers with KVM Separation. +# +# runtime_supports_kvm = ["kata"] + # Paths to look for a valid OCI runtime (runc, runv, kata, etc) [engine.runtimes] # runc = [ @@ -376,6 +393,8 @@ # "/usr/local/sbin/kata-runtime", # "/sbin/kata-runtime", # "/bin/kata-runtime", +# "/usr/bin/kata-qemu", +# "/usr/bin/kata-fc", # ] # Number of seconds to wait for container to exit before sending kill signal. diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go index 78bfd8a28..8b87d3725 100644 --- a/vendor/github.com/containers/common/pkg/config/default.go +++ b/vendor/github.com/containers/common/pkg/config/default.go @@ -148,6 +148,7 @@ func DefaultConfig() (*Config, error) { Annotations: []string{}, ApparmorProfile: DefaultApparmorProfile, CgroupNS: "private", + Cgroups: "enabled", DefaultCapabilities: DefaultCapabilities, DefaultSysctls: []string{}, DefaultUlimits: getDefaultProcessLimits(), @@ -246,6 +247,8 @@ func defaultConfigFromMemory() (*EngineConfig, error) { "/usr/local/sbin/kata-runtime", "/sbin/kata-runtime", "/bin/kata-runtime", + "/usr/bin/kata-qemu", + "/usr/bin/kata-fc", }, } c.ConmonEnvVars = []string{ @@ -267,6 +270,7 @@ func defaultConfigFromMemory() (*EngineConfig, error) { "runc", } c.RuntimeSupportsNoCgroups = []string{"crun"} + c.RuntimeSupportsKVM = []string{"kata", "kata-runtime", "kata-qemu", "kata-fc"} c.InitPath = DefaultInitPath c.NoPivotRoot = false @@ -436,6 +440,11 @@ func (c *Config) CgroupNS() string { return c.Containers.CgroupNS } +// Cgroups returns whether to containers with cgroup confinement +func (c *Config) Cgroups() string { + return c.Containers.Cgroups +} + // UTSNS returns the default UTS Namespace configuration to run containers with func (c *Config) UTSNS() string { return c.Containers.UTSNS diff --git a/vendor/modules.txt b/vendor/modules.txt index 535090e81..3b45161da 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -82,7 +82,7 @@ github.com/containers/buildah/pkg/secrets github.com/containers/buildah/pkg/supplemented github.com/containers/buildah/pkg/umask github.com/containers/buildah/util -# github.com/containers/common v0.8.1 +# github.com/containers/common v0.9.1 github.com/containers/common/pkg/apparmor github.com/containers/common/pkg/capabilities github.com/containers/common/pkg/cgroupv2 |