diff options
-rw-r--r-- | CONTRIBUTING.md | 84 | ||||
-rw-r--r-- | README.md | 17 | ||||
-rw-r--r-- | cmd/podman/cleanup.go | 2 | ||||
-rw-r--r-- | cmd/podman/libpodruntime/runtime.go | 3 | ||||
-rw-r--r-- | cmd/podman/logs.go | 2 | ||||
-rw-r--r-- | cmd/podman/play_kube.go | 2 | ||||
-rw-r--r-- | docs/libpod.conf.5.md | 6 | ||||
-rw-r--r-- | docs/podman-generate-kube.1.md | 4 | ||||
-rw-r--r-- | docs/podman-play-kube.1.md | 4 | ||||
-rw-r--r-- | libpod.conf | 6 | ||||
-rw-r--r-- | libpod/boltdb_state.go | 2 | ||||
-rw-r--r-- | libpod/boltdb_state_internal.go | 11 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 13 | ||||
-rw-r--r-- | libpod/info.go | 1 | ||||
-rw-r--r-- | libpod/options.go | 22 | ||||
-rw-r--r-- | libpod/runtime.go | 45 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 5 | ||||
-rw-r--r-- | libpod/state.go | 1 | ||||
-rw-r--r-- | libpod/volume.go | 18 | ||||
-rw-r--r-- | vendor.conf | 2 | ||||
-rw-r--r-- | vendor/github.com/containers/image/pkg/blobinfocache/memory.go | 20 | ||||
-rw-r--r-- | vendor/github.com/containers/image/version/version.go | 2 |
22 files changed, 245 insertions, 27 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 26e5473b2..b1b166fef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,5 @@ ![PODMAN logo](logo/podman-logo-source.svg) -# Contributing to Libpod +# Contributing to libpod We'd love to have you join the community! Below summarizes the processes that we follow. @@ -7,6 +7,7 @@ that we follow. ## Topics * [Reporting Issues](#reporting-issues) +* [Contributing to libpod](#contributing-to-libpod) * [Submitting Pull Requests](#submitting-pull-requests) * [Communications](#communications) @@ -26,6 +27,87 @@ The easier it is for us to reproduce it, the faster it'll be fixed! Please don't include any private/sensitive information in your issue! +## Contributing to libpod + +This section describes how to start a contribution to libpod. + +### Prepare your environment + +Read the [install documentation to see how to install dependencies](install.md) . + +The install documentation will illustrate the following steps: +- install libs and tools +- check installed versions +- configure network +- how to install libpod from sources + +### Fork and clone libpod + +First you need to fork this project on GitHub. + +Be sure to have [defined your `$GOPATH` environment variable](https://github.com/golang/go/wiki/GOPATH). + +Create a path that correspond to your clone `mkdir -p $GOPATH/github.com/<you>`. + +Clone your fork locally: +```shell +$ git clone git@github.com:<you>/libpod github.com/<you> $GOPATH/github.com/<you>/libpod +$ cd $GOPATH/github.com/<you>/libpod +``` + +You can also use `go get` to clone your fork: +```shell +$ go get github.com:<you>/libpod +$ cd $GOPATH/github.com/<you>/libpod +``` + +### Deal with make + +Libpod use a Makefile to realize common action like building etc... + +You can list available actions by using: +```shell +$ make help +Usage: make <target> +...output... +``` + +### Install tools + +Makefile allow you to install needed tools: +```shell +$ make install.tools +``` + +### Building binaries and test your changes + +To test your changes do `make binaries` to generate your binaries. + +Your binaries are created inside the `bin/` directory and you can test your changes: +```shell +$ bin/podman -h +bin/podman -h +NAME: + podman - manage pods and images + +USAGE: + podman [global options] command [command options] [arguments...] + +VERSION: + 1.0.1-dev + +COMMANDS: + attach Attach to a running container + build Build an image using instructions from Dockerfiles + commit Create new image based on the changed container + container Manage Containers + cp Copy files/folders between a container and the local filesystem +``` + +Well, you can now create your own branch, apply changes on it, and then submitting your pull request. + +For further reading about branching [you can read this document](https://herve.beraud.io/containers/linux/podman/isolate/environment/2019/02/06/how-to-hack-on-podman.html). + ## Submitting Pull Requests No Pull Request (PR) is too small! Typos, additional comments in the code, @@ -31,10 +31,19 @@ This project tests all builds against each supported version of Fedora, the late ## Out of scope -* Signing and pushing images to various image storages. - See [Skopeo](https://github.com/containers/skopeo/). -* Container Runtimes daemons for working with the Kubernetes CRI interface. - See [CRI-O](https://github.com/kubernetes-sigs/cri-o). +* Specializing in signing and pushing images to various storage backends. + See [Skopeo](https://github.com/containers/skopeo/) for those tasks. +* Container runtimes daemons for working with the Kubernetes CRI interface. + [CRI-O](https://github.com/kubernetes-sigs/cri-o) specializes in that. +* Supporting `docker-compose`. We believe that Kubernetes is the defacto + standard for composing Pods and for orchestrating containers, making + Kubernetes YAML a defacto standard file format. Hence, Podman allows the + creation and execution of Pods from a Kubernetes YAML file (see + [podman-play-kube](https://github.com/containers/libpod/blob/master/docs/podman-play-kube.1.md)). + Podman can also generate Kubernetes YAML based on a container or Pod (see + [podman-generate-kube](https://github.com/containers/libpod/blob/master/docs/podman-generate-kube.1.md)), + which allows for an easy transition from a local development environment + to a production Kubernetes cluster. ## OCI Projects Plans diff --git a/cmd/podman/cleanup.go b/cmd/podman/cleanup.go index d68255aa2..33d456643 100644 --- a/cmd/podman/cleanup.go +++ b/cmd/podman/cleanup.go @@ -60,7 +60,7 @@ func cleanupCmd(c *cliconfig.CleanupValues) error { for _, ctr := range cleanupContainers { hadError := false if c.Remove { - if err := runtime.RemoveContainer(ctx, ctr, false, false); err != nil { + if err := runtime.RemoveContainer(ctx, ctr, false, true); err != nil { if lastError != nil { fmt.Fprintln(os.Stderr, lastError) } diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go index 880b281bd..f4ddf3521 100644 --- a/cmd/podman/libpodruntime/runtime.go +++ b/cmd/podman/libpodruntime/runtime.go @@ -21,7 +21,7 @@ func GetRuntime(c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { func getRuntime(c *cliconfig.PodmanCommand, renumber bool) (*libpod.Runtime, error) { options := []libpod.RuntimeOption{} - storageOpts, volumePath, err := util.GetDefaultStoreOptions() + storageOpts, _, err := util.GetDefaultStoreOptions() if err != nil { return nil, err } @@ -120,7 +120,6 @@ func getRuntime(c *cliconfig.PodmanCommand, renumber bool) (*libpod.Runtime, err infraCommand, _ := c.Flags().GetString("infra-command") options = append(options, libpod.WithDefaultInfraCommand(infraCommand)) } - options = append(options, libpod.WithVolumePath(volumePath)) if c.Flags().Changed("config") { return libpod.NewRuntimeFromConfig(c.GlobalFlags.Config, options...) } diff --git a/cmd/podman/logs.go b/cmd/podman/logs.go index 97d835d8f..40ae2c846 100644 --- a/cmd/podman/logs.go +++ b/cmd/podman/logs.go @@ -38,7 +38,7 @@ func init() { flags := logsCommand.Flags() flags.BoolVar(&logsCommand.Details, "details", false, "Show extra details provided to the logs") flags.BoolVarP(&logsCommand.Follow, "follow", "f", false, "Follow log output. The default is false") - flags.BoolVarP(&waitCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") + flags.BoolVarP(&logsCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.StringVar(&logsCommand.Since, "since", "", "Show logs since TIMESTAMP") flags.Uint64Var(&logsCommand.Tail, "tail", 0, "Output the specified number of LINES at the end of the logs. Defaults to 0, which prints all lines") flags.BoolVarP(&logsCommand.Timestamps, "timestamps", "t", false, "Output the timestamps in the log") diff --git a/cmd/podman/play_kube.go b/cmd/podman/play_kube.go index a59460b71..1a45cbed9 100644 --- a/cmd/podman/play_kube.go +++ b/cmd/podman/play_kube.go @@ -153,7 +153,7 @@ func playKubeYAMLCmd(c *cliconfig.KubePlayValues) error { // start the containers for _, ctr := range containers { - if err := ctr.Start(ctx, false); err != nil { + if err := ctr.Start(ctx, true); err != nil { // Making this a hard failure here to avoid a mess // the other containers are in created status return err diff --git a/docs/libpod.conf.5.md b/docs/libpod.conf.5.md index 0836c45fa..9a19e1224 100644 --- a/docs/libpod.conf.5.md +++ b/docs/libpod.conf.5.md @@ -13,7 +13,7 @@ libpod to manage containers. Default transport method for pulling and pushing images **runtime**="" - Default OCI runtime to use if nothing is specified + Default OCI runtime to use if nothing is specified in **runtimes** **runtimes** For each OCI runtime, specify a list of paths to look for. The first one found is used. @@ -87,6 +87,10 @@ libpod to manage containers. The default number available is 2048. If this is changed, a lock renumbering must be performed, using the `podman system renumber` command. +**volume_path**="" + Directory where named volumes will be created in using the default volume driver. + By default this will be configured relative to where containers/storage stores containers. + ## FILES `/usr/share/containers/libpod.conf`, default libpod configuration path diff --git a/docs/podman-generate-kube.1.md b/docs/podman-generate-kube.1.md index 5236f23fe..d4bed8ab1 100644 --- a/docs/podman-generate-kube.1.md +++ b/docs/podman-generate-kube.1.md @@ -19,6 +19,8 @@ The **service** option can be used to generate a Service specification for the c if the object has portmap bindings, the service specification will include a NodePort declaration to expose the service. A random port is assigned by Podman in the specification. +Note that the generated Kubernetes YAML file can be used to re-run the deployment via podman-play-kube(1). + # OPTIONS: **s** **--service** @@ -145,7 +147,7 @@ status: ``` ## SEE ALSO -podman(1), podman-container, podman-pod, podman-play +podman(1), podman-container(1), podman-pod(1), podman-play-kube(1) # HISTORY Decemeber 2018, Originally compiled by Brent Baude (bbaude at redhat dot com) diff --git a/docs/podman-play-kube.1.md b/docs/podman-play-kube.1.md index 3fd9746a5..2264f7a88 100644 --- a/docs/podman-play-kube.1.md +++ b/docs/podman-play-kube.1.md @@ -20,7 +20,7 @@ kubernetes_input.yml the pod and containers described in the YAML. The containers within the pod are then started and the ID of the new Pod is output. -Ideally the input file would be one created by Podman. This would guarantee a smooth import and expected results. +Ideally the input file would be one created by Podman (see podman-generate-kube(1)). This would guarantee a smooth import and expected results. # OPTIONS: @@ -72,7 +72,7 @@ $ podman play kube demo.yml ``` ## SEE ALSO -podman(1), podman-container(1), podman-pod(1), podman-generate(1), podman-play(1) +podman(1), podman-container(1), podman-pod(1), podman-generate-kube(1), podman-play(1) # HISTORY Decemeber 2018, Originally compiled by Brent Baude (bbaude at redhat dot com) diff --git a/libpod.conf b/libpod.conf index 8d6158ed5..211ba106d 100644 --- a/libpod.conf +++ b/libpod.conf @@ -93,6 +93,12 @@ pause_command = "/pause" # 'podman system renumber' command). num_locks = 2048 +# Directory for libpod named volumes. +# By default, this will be configured relative to where containers/storage +# stores containers. +# Uncomment to change location from this default. +#volume_path = "/var/lib/containers/storage/volumes" + # Default OCI runtime runtime = "runc" diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index 25ef5cd0e..c226a0617 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -261,12 +261,14 @@ func (s *BoltState) GetDBConfig() (*DBConfig, error) { storageRoot := configBucket.Get(graphRootKey) storageTmp := configBucket.Get(runRootKey) graphDriver := configBucket.Get(graphDriverKey) + volumePath := configBucket.Get(volPathKey) cfg.LibpodRoot = string(libpodRoot) cfg.LibpodTmp = string(libpodTmp) cfg.StorageRoot = string(storageRoot) cfg.StorageTmp = string(storageTmp) cfg.GraphDriver = string(graphDriver) + cfg.VolumePath = string(volumePath) return nil }) diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go index 3d749849d..936ccbf4c 100644 --- a/libpod/boltdb_state_internal.go +++ b/libpod/boltdb_state_internal.go @@ -38,6 +38,7 @@ const ( graphRootName = "graph-root" graphDriverName = "graph-driver-name" osName = "os" + volPathName = "volume-path" ) var ( @@ -67,6 +68,7 @@ var ( graphRootKey = []byte(graphRootName) graphDriverKey = []byte(graphDriverName) osKey = []byte(osName) + volPathKey = []byte(volPathName) ) // Check if the configuration of the database is compatible with the @@ -105,10 +107,15 @@ func checkRuntimeConfig(db *bolt.DB, rt *Runtime) error { return err } - return validateDBAgainstConfig(configBkt, "storage graph driver", + if err := validateDBAgainstConfig(configBkt, "storage graph driver", rt.config.StorageConfig.GraphDriverName, graphDriverKey, - storage.DefaultStoreOptions.GraphDriverName) + storage.DefaultStoreOptions.GraphDriverName); err != nil { + return err + } + + return validateDBAgainstConfig(configBkt, "volume path", + rt.config.VolumePath, volPathKey, "") }) return err diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index f182b6bdf..b074efa3a 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -481,6 +481,19 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO if c.state.State != ContainerStateRunning { return errors.Wrapf(ErrCtrStateInvalid, "%q is not running, cannot checkpoint", c.state.State) } + + // Create the CRIU log file and label it + dumpLog := filepath.Join(c.bundlePath(), "dump.log") + + logFile, err := os.OpenFile(dumpLog, os.O_CREATE, 0600) + if err != nil { + return errors.Wrapf(err, "failed to create CRIU log file %q", dumpLog) + } + logFile.Close() + if err = label.SetFileLabel(dumpLog, c.MountLabel()); err != nil { + return errors.Wrapf(err, "failed to label CRIU log file %q", dumpLog) + } + if err := c.runtime.ociRuntime.checkpointContainer(c, options); err != nil { return err } diff --git a/libpod/info.go b/libpod/info.go index 191ce6810..62088b730 100644 --- a/libpod/info.go +++ b/libpod/info.go @@ -121,6 +121,7 @@ func (r *Runtime) storeInfo() (map[string]interface{}, error) { info["RunRoot"] = r.store.RunRoot() info["GraphDriverName"] = r.store.GraphDriverName() info["GraphOptions"] = r.store.GraphOptions() + info["VolumePath"] = r.config.VolumePath statusPairs, err := r.store.Status() if err != nil { return nil, err diff --git a/libpod/options.go b/libpod/options.go index e22c81f91..1e8592a25 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -47,6 +47,11 @@ func WithStorageConfig(config storage.StoreOptions) RuntimeOption { rt.config.StaticDir = filepath.Join(config.GraphRoot, "libpod") rt.configuredFrom.libpodStaticDirSet = true + // Also set libpod volume path, so we are a subdirectory + // of the c/storage store by default + rt.config.VolumePath = filepath.Join(config.GraphRoot, "volumes") + rt.configuredFrom.volPathSet = true + setField = true } @@ -359,6 +364,7 @@ func WithVolumePath(volPath string) RuntimeOption { } rt.config.VolumePath = volPath + rt.configuredFrom.volPathSet = true return nil } @@ -1242,6 +1248,22 @@ func WithVolumeOptions(options map[string]string) VolumeCreateOption { } } +// withSetCtrSpecific sets a bool notifying libpod that a volume was created +// specifically for a container. +// These volumes will be removed when the container is removed and volumes are +// also specified for removal. +func withSetCtrSpecific() VolumeCreateOption { + return func(volume *Volume) error { + if volume.valid { + return ErrVolumeFinalized + } + + volume.config.IsCtrSpecific = true + + return nil + } +} + // Pod Creation Options // WithPodName sets the name of the pod. diff --git a/libpod/runtime.go b/libpod/runtime.go index 94dbf37dd..827c22f5b 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -123,7 +123,10 @@ type RuntimeConfig struct { // Not included in on-disk config, use the dedicated containers/storage // configuration file instead StorageConfig storage.StoreOptions `toml:"-"` - VolumePath string `toml:"volume_path"` + // VolumePath is the default location that named volumes will be created + // under. This convention is followed by the default volume driver, but + // may not be by other drivers. + VolumePath string `toml:"volume_path"` // ImageDefaultTransport is the default transport method used to fetch // images ImageDefaultTransport string `toml:"image_default_transport"` @@ -232,12 +235,14 @@ type runtimeConfiguredFrom struct { storageRunRootSet bool libpodStaticDirSet bool libpodTmpDirSet bool + volPathSet bool } var ( defaultRuntimeConfig = RuntimeConfig{ // Leave this empty so containers/storage will use its defaults StorageConfig: storage.StoreOptions{}, + VolumePath: filepath.Join(storage.DefaultStoreOptions.GraphRoot, "volumes"), ImageDefaultTransport: DefaultTransport, StateType: BoltDBStateStore, OCIRuntime: "runc", @@ -400,6 +405,9 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) { if tmpConfig.TmpDir != "" { runtime.configuredFrom.libpodTmpDirSet = true } + if tmpConfig.VolumePath != "" { + runtime.configuredFrom.volPathSet = true + } if _, err := toml.Decode(string(contents), runtime.config); err != nil { return nil, errors.Wrapf(err, "error decoding configuration file %s", configPath) @@ -526,6 +534,16 @@ func makeRuntime(runtime *Runtime) (err error) { if runtime.config.OCIRuntime != "" && runtime.config.OCIRuntime[0] == '/' { foundRuntime = true runtime.ociRuntimePath = OCIRuntimePath{Name: filepath.Base(runtime.config.OCIRuntime), Paths: []string{runtime.config.OCIRuntime}} + stat, err := os.Stat(runtime.config.OCIRuntime) + if err != nil { + if os.IsNotExist(err) { + return errors.Wrapf(err, "the specified OCI runtime %s does not exist", runtime.config.OCIRuntime) + } + return errors.Wrapf(err, "cannot stat the OCI runtime path %s", runtime.config.OCIRuntime) + } + if !stat.Mode().IsRegular() { + return fmt.Errorf("the specified OCI runtime %s is not a valid file", runtime.config.OCIRuntime) + } } else { // If not, look it up in the configuration. paths := runtime.config.OCIRuntimes[runtime.config.OCIRuntime] @@ -614,29 +632,52 @@ func makeRuntime(runtime *Runtime) (err error) { if !runtime.configuredFrom.storageGraphDriverSet && dbConfig.GraphDriver != "" { if runtime.config.StorageConfig.GraphDriverName != dbConfig.GraphDriver && runtime.config.StorageConfig.GraphDriverName != "" { - logrus.Errorf("User-selected graph driver %s overwritten by graph driver %s from database - delete libpod local files to resolve", + logrus.Errorf("User-selected graph driver %q overwritten by graph driver %q from database - delete libpod local files to resolve", runtime.config.StorageConfig.GraphDriverName, dbConfig.GraphDriver) } runtime.config.StorageConfig.GraphDriverName = dbConfig.GraphDriver } if !runtime.configuredFrom.storageGraphRootSet && dbConfig.StorageRoot != "" { + if runtime.config.StorageConfig.GraphRoot != dbConfig.StorageRoot && + runtime.config.StorageConfig.GraphRoot != "" { + logrus.Debugf("Overriding graph root %q with %q from database", + runtime.config.StorageConfig.GraphRoot, dbConfig.StorageRoot) + } runtime.config.StorageConfig.GraphRoot = dbConfig.StorageRoot } if !runtime.configuredFrom.storageRunRootSet && dbConfig.StorageTmp != "" { + if runtime.config.StorageConfig.RunRoot != dbConfig.StorageTmp && + runtime.config.StorageConfig.RunRoot != "" { + logrus.Debugf("Overriding run root %q with %q from database", + runtime.config.StorageConfig.RunRoot, dbConfig.StorageTmp) + } runtime.config.StorageConfig.RunRoot = dbConfig.StorageTmp } if !runtime.configuredFrom.libpodStaticDirSet && dbConfig.LibpodRoot != "" { + if runtime.config.StaticDir != dbConfig.LibpodRoot && runtime.config.StaticDir != "" { + logrus.Debugf("Overriding static dir %q with %q from database", runtime.config.StaticDir, dbConfig.LibpodRoot) + } runtime.config.StaticDir = dbConfig.LibpodRoot } if !runtime.configuredFrom.libpodTmpDirSet && dbConfig.LibpodTmp != "" { + if runtime.config.TmpDir != dbConfig.LibpodTmp && runtime.config.TmpDir != "" { + logrus.Debugf("Overriding tmp dir %q with %q from database", runtime.config.TmpDir, dbConfig.LibpodTmp) + } runtime.config.TmpDir = dbConfig.LibpodTmp } + if !runtime.configuredFrom.volPathSet && dbConfig.VolumePath != "" { + if runtime.config.VolumePath != dbConfig.VolumePath && runtime.config.VolumePath != "" { + logrus.Debugf("Overriding volume path %q with %q from database", runtime.config.VolumePath, dbConfig.VolumePath) + } + runtime.config.VolumePath = dbConfig.VolumePath + } logrus.Debugf("Using graph driver %s", runtime.config.StorageConfig.GraphDriverName) logrus.Debugf("Using graph root %s", runtime.config.StorageConfig.GraphRoot) logrus.Debugf("Using run root %s", runtime.config.StorageConfig.RunRoot) logrus.Debugf("Using static dir %s", runtime.config.StaticDir) logrus.Debugf("Using tmp dir %s", runtime.config.TmpDir) + logrus.Debugf("Using volume path %s", runtime.config.VolumePath) // Validate our config against the database, now that we've set our // final storage configuration diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 2ec8d0795..cfa4f9654 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -180,7 +180,7 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options .. if vol.Source[0] != '/' && isNamedVolume(vol.Source) { volInfo, err := r.state.Volume(vol.Source) if err != nil { - newVol, err := r.newVolume(ctx, WithVolumeName(vol.Source)) + newVol, err := r.newVolume(ctx, WithVolumeName(vol.Source), withSetCtrSpecific()) if err != nil { return nil, errors.Wrapf(err, "error creating named volume %q", vol.Source) } @@ -421,6 +421,9 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool, for _, v := range volumes { if volume, err := runtime.state.Volume(v); err == nil { + if !volume.IsCtrSpecific() { + continue + } if err := runtime.removeVolume(ctx, volume, false); err != nil && err != ErrNoSuchVolume && err != ErrVolumeBeingUsed { logrus.Errorf("cleanup volume (%s): %v", v, err) } diff --git a/libpod/state.go b/libpod/state.go index 98282fc83..4296fc3cd 100644 --- a/libpod/state.go +++ b/libpod/state.go @@ -8,6 +8,7 @@ type DBConfig struct { StorageRoot string StorageTmp string GraphDriver string + VolumePath string } // State is a storage backend for libpod's current state. diff --git a/libpod/volume.go b/libpod/volume.go index 74878b6a4..0c7618841 100644 --- a/libpod/volume.go +++ b/libpod/volume.go @@ -15,11 +15,12 @@ type VolumeConfig struct { // Name of the volume Name string `json:"name"` - Labels map[string]string `json:"labels"` - MountPoint string `json:"mountPoint"` - Driver string `json:"driver"` - Options map[string]string `json:"options"` - Scope string `json:"scope"` + Labels map[string]string `json:"labels"` + MountPoint string `json:"mountPoint"` + Driver string `json:"driver"` + Options map[string]string `json:"options"` + Scope string `json:"scope"` + IsCtrSpecific bool `json:"ctrSpecific"` } // Name retrieves the volume's name @@ -60,3 +61,10 @@ func (v *Volume) Options() map[string]string { func (v *Volume) Scope() string { return v.config.Scope } + +// IsCtrSpecific returns whether this volume was created specifically for a +// given container. Images with this set to true will be removed when the +// container is removed with the Volumes parameter set to true. +func (v *Volume) IsCtrSpecific() bool { + return v.config.IsCtrSpecific +} diff --git a/vendor.conf b/vendor.conf index 445f0844a..678807d1c 100644 --- a/vendor.conf +++ b/vendor.conf @@ -15,7 +15,7 @@ github.com/containerd/cgroups 39b18af02c4120960f517a3a4c2588fabb61d02c github.com/containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d github.com/containernetworking/cni v0.7.0-alpha1 github.com/containernetworking/plugins v0.7.4 -github.com/containers/image v1.4 +github.com/containers/image v1.5 github.com/vbauerster/mpb v3.3.4 github.com/mattn/go-isatty v0.0.4 github.com/VividCortex/ewma v1.1.1 diff --git a/vendor/github.com/containers/image/pkg/blobinfocache/memory.go b/vendor/github.com/containers/image/pkg/blobinfocache/memory.go index 1ce7dee13..cf6ca5263 100644 --- a/vendor/github.com/containers/image/pkg/blobinfocache/memory.go +++ b/vendor/github.com/containers/image/pkg/blobinfocache/memory.go @@ -1,6 +1,7 @@ package blobinfocache import ( + "sync" "time" "github.com/containers/image/types" @@ -17,6 +18,7 @@ type locationKey struct { // memoryCache implements an in-memory-only BlobInfoCache type memoryCache struct { + mutex *sync.Mutex // synchronizes concurrent accesses uncompressedDigests map[digest.Digest]digest.Digest digestsByUncompressed map[digest.Digest]map[digest.Digest]struct{} // stores a set of digests for each uncompressed digest knownLocations map[locationKey]map[types.BICLocationReference]time.Time // stores last known existence time for each location reference @@ -28,6 +30,7 @@ type memoryCache struct { // Manual users of types.{ImageSource,ImageDestination} might also use this instead of a persistent cache. func NewMemoryCache() types.BlobInfoCache { return &memoryCache{ + mutex: new(sync.Mutex), uncompressedDigests: map[digest.Digest]digest.Digest{}, digestsByUncompressed: map[digest.Digest]map[digest.Digest]struct{}{}, knownLocations: map[locationKey]map[types.BICLocationReference]time.Time{}, @@ -38,6 +41,15 @@ func NewMemoryCache() types.BlobInfoCache { // May return anyDigest if it is known to be uncompressed. // Returns "" if nothing is known about the digest (it may be compressed or uncompressed). func (mem *memoryCache) UncompressedDigest(anyDigest digest.Digest) digest.Digest { + mem.mutex.Lock() + defer mem.mutex.Unlock() + return mem.uncompressedDigest(anyDigest) +} + +// uncompressedDigest returns an uncompressed digest corresponding to anyDigest. +// May return anyDigest if it is known to be uncompressed. +// Returns "" if nothing is known about the digest (it may be compressed or uncompressed). +func (mem *memoryCache) uncompressedDigest(anyDigest digest.Digest) digest.Digest { if d, ok := mem.uncompressedDigests[anyDigest]; ok { return d } @@ -56,6 +68,8 @@ func (mem *memoryCache) UncompressedDigest(anyDigest digest.Digest) digest.Diges // because a manifest/config pair exists); otherwise the cache could be poisoned and allow substituting unexpected blobs. // (Eventually, the DiffIDs in image config could detect the substitution, but that may be too late, and not all image formats contain that data.) func (mem *memoryCache) RecordDigestUncompressedPair(anyDigest digest.Digest, uncompressed digest.Digest) { + mem.mutex.Lock() + defer mem.mutex.Unlock() if previous, ok := mem.uncompressedDigests[anyDigest]; ok && previous != uncompressed { logrus.Warnf("Uncompressed digest for blob %s previously recorded as %s, now %s", anyDigest, previous, uncompressed) } @@ -72,6 +86,8 @@ func (mem *memoryCache) RecordDigestUncompressedPair(anyDigest digest.Digest, un // RecordKnownLocation records that a blob with the specified digest exists within the specified (transport, scope) scope, // and can be reused given the opaque location data. func (mem *memoryCache) RecordKnownLocation(transport types.ImageTransport, scope types.BICTransportScope, blobDigest digest.Digest, location types.BICLocationReference) { + mem.mutex.Lock() + defer mem.mutex.Unlock() key := locationKey{transport: transport.Name(), scope: scope, blobDigest: blobDigest} locationScope, ok := mem.knownLocations[key] if !ok { @@ -103,11 +119,13 @@ func (mem *memoryCache) appendReplacementCandidates(candidates []candidateWithTi // data from previous RecordDigestUncompressedPair calls is used to also look up variants of the blob which have the same // uncompressed digest. func (mem *memoryCache) CandidateLocations(transport types.ImageTransport, scope types.BICTransportScope, primaryDigest digest.Digest, canSubstitute bool) []types.BICReplacementCandidate { + mem.mutex.Lock() + defer mem.mutex.Unlock() res := []candidateWithTime{} res = mem.appendReplacementCandidates(res, transport, scope, primaryDigest) var uncompressedDigest digest.Digest // = "" if canSubstitute { - if uncompressedDigest = mem.UncompressedDigest(primaryDigest); uncompressedDigest != "" { + if uncompressedDigest = mem.uncompressedDigest(primaryDigest); uncompressedDigest != "" { otherDigests := mem.digestsByUncompressed[uncompressedDigest] // nil if not present in the map for d := range otherDigests { if d != primaryDigest && d != uncompressedDigest { diff --git a/vendor/github.com/containers/image/version/version.go b/vendor/github.com/containers/image/version/version.go index 10075992d..2a3bc1b5c 100644 --- a/vendor/github.com/containers/image/version/version.go +++ b/vendor/github.com/containers/image/version/version.go @@ -11,7 +11,7 @@ const ( VersionPatch = 5 // VersionDev indicates development branch. Releases will be empty string. - VersionDev = "-dev" + VersionDev = "" ) // Version is the specification version that the package types support. |