diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/image/pull.go | 25 | ||||
-rw-r--r-- | libpod/oci.go | 12 | ||||
-rw-r--r-- | libpod/oci_internal_linux.go | 16 | ||||
-rw-r--r-- | libpod/oci_linux.go | 6 | ||||
-rw-r--r-- | libpod/options.go | 44 | ||||
-rw-r--r-- | libpod/runtime.go | 6 | ||||
-rw-r--r-- | libpod/runtime_volume_linux.go | 7 | ||||
-rw-r--r-- | libpod/volume.go | 46 | ||||
-rw-r--r-- | libpod/volume_inspect.go | 70 |
9 files changed, 172 insertions, 60 deletions
diff --git a/libpod/image/pull.go b/libpod/image/pull.go index 78cfe3626..dbf3a4ef5 100644 --- a/libpod/image/pull.go +++ b/libpod/image/pull.go @@ -13,6 +13,7 @@ import ( dockerarchive "github.com/containers/image/docker/archive" "github.com/containers/image/docker/tarfile" ociarchive "github.com/containers/image/oci/archive" + oci "github.com/containers/image/oci/layout" is "github.com/containers/image/storage" "github.com/containers/image/transports" "github.com/containers/image/transports/alltransports" @@ -37,6 +38,9 @@ var ( DirTransport = directory.Transport.Name() // DockerTransport is the transport for docker registries DockerTransport = docker.Transport.Name() + // OCIDirTransport is the transport for pushing and pulling + // images to and from a directory containing an OCI image + OCIDirTransport = oci.Transport.Name() // AtomicTransport is the transport for atomic registries AtomicTransport = "atomic" // DefaultTransport is a prefix that we apply to an image name @@ -189,12 +193,12 @@ func (ir *Runtime) pullGoalFromImageReference(ctx context.Context, srcRef types. return ir.getSinglePullRefPairGoal(srcRef, dest) case DirTransport: - path := srcRef.StringWithinTransport() - image := path - if image[:1] == "/" { - // Set localhost as the registry so docker.io isn't prepended, and the path becomes the repository - image = DefaultLocalRegistry + image - } + image := toLocalImageName(srcRef.StringWithinTransport()) + return ir.getSinglePullRefPairGoal(srcRef, image) + + case OCIDirTransport: + split := strings.SplitN(srcRef.StringWithinTransport(), ":", 2) + image := toLocalImageName(split[0]) return ir.getSinglePullRefPairGoal(srcRef, image) default: @@ -202,6 +206,15 @@ func (ir *Runtime) pullGoalFromImageReference(ctx context.Context, srcRef types. } } +// toLocalImageName converts an image name into a 'localhost/' prefixed one +func toLocalImageName(imageName string) string { + return fmt.Sprintf( + "%s/%s", + DefaultLocalRegistry, + strings.TrimLeft(imageName, "/"), + ) +} + // pullImageFromHeuristicSource pulls an image based on inputName, which is heuristically parsed and may involve configured registries. // Use pullImageFromReference if the source is known precisely. func (ir *Runtime) pullImageFromHeuristicSource(ctx context.Context, inputName string, writer io.Writer, authfile, signaturePolicyPath string, signingOptions SigningOptions, dockerOptions *DockerRegistryOptions, label *string) ([]string, error) { diff --git a/libpod/oci.go b/libpod/oci.go index 4ba3114e3..8a873ca5b 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -213,7 +213,7 @@ func bindPorts(ports []ocicni.PortMapping) ([]*os.File, error) { func (r *OCIRuntime) updateContainerStatus(ctr *Container, useRuntime bool) error { exitFile := ctr.exitFilePath() - runtimeDir, err := util.GetRootlessRuntimeDir() + runtimeDir, err := util.GetRuntimeDir() if err != nil { return err } @@ -336,7 +336,7 @@ func (r *OCIRuntime) updateContainerStatus(ctr *Container, useRuntime bool) erro // Sets time the container was started, but does not save it. func (r *OCIRuntime) startContainer(ctr *Container) error { // TODO: streams should probably *not* be our STDIN/OUT/ERR - redirect to buffers? - runtimeDir, err := util.GetRootlessRuntimeDir() + runtimeDir, err := util.GetRuntimeDir() if err != nil { return err } @@ -356,7 +356,7 @@ func (r *OCIRuntime) startContainer(ctr *Container) error { // killContainer sends the given signal to the given container func (r *OCIRuntime) killContainer(ctr *Container, signal uint) error { logrus.Debugf("Sending signal %d to container %s", signal, ctr.ID()) - runtimeDir, err := util.GetRootlessRuntimeDir() + runtimeDir, err := util.GetRuntimeDir() if err != nil { return err } @@ -370,7 +370,7 @@ func (r *OCIRuntime) killContainer(ctr *Container, signal uint) error { // deleteContainer deletes a container from the OCI runtime func (r *OCIRuntime) deleteContainer(ctr *Container) error { - runtimeDir, err := util.GetRootlessRuntimeDir() + runtimeDir, err := util.GetRuntimeDir() if err != nil { return err } @@ -380,7 +380,7 @@ func (r *OCIRuntime) deleteContainer(ctr *Container) error { // pauseContainer pauses the given container func (r *OCIRuntime) pauseContainer(ctr *Container) error { - runtimeDir, err := util.GetRootlessRuntimeDir() + runtimeDir, err := util.GetRuntimeDir() if err != nil { return err } @@ -390,7 +390,7 @@ func (r *OCIRuntime) pauseContainer(ctr *Container) error { // unpauseContainer unpauses the given container func (r *OCIRuntime) unpauseContainer(ctr *Container) error { - runtimeDir, err := util.GetRootlessRuntimeDir() + runtimeDir, err := util.GetRuntimeDir() if err != nil { return err } diff --git a/libpod/oci_internal_linux.go b/libpod/oci_internal_linux.go index 6e4ee2cf2..48b7370e0 100644 --- a/libpod/oci_internal_linux.go +++ b/libpod/oci_internal_linux.go @@ -36,7 +36,7 @@ import ( func (r *OCIRuntime) createOCIContainer(ctr *Container, restoreOptions *ContainerCheckpointOptions) (err error) { var stderrBuf bytes.Buffer - runtimeDir, err := util.GetRootlessRuntimeDir() + runtimeDir, err := util.GetRuntimeDir() if err != nil { return err } @@ -449,6 +449,15 @@ func readConmonPipeData(pipe *os.File, ociLog string) (int, error) { select { case ss := <-ch: if ss.err != nil { + if ociLog != "" { + ociLogData, err := ioutil.ReadFile(ociLog) + if err == nil { + var ociErr ociError + if err := json.Unmarshal(ociLogData, &ociErr); err == nil { + return -1, getOCIRuntimeError(ociErr.Msg) + } + } + } return -1, errors.Wrapf(ss.err, "error reading container (probably exited) json message") } logrus.Debugf("Received: %d", ss.si.Data) @@ -476,10 +485,11 @@ func readConmonPipeData(pipe *os.File, ociLog string) (int, error) { } func getOCIRuntimeError(runtimeMsg string) error { - if match, _ := regexp.MatchString(".*permission denied.*", runtimeMsg); match { + r := strings.ToLower(runtimeMsg) + if match, _ := regexp.MatchString(".*permission denied.*|.*operation not permitted.*", r); match { return errors.Wrapf(define.ErrOCIRuntimePermissionDenied, "%s", strings.Trim(runtimeMsg, "\n")) } - if match, _ := regexp.MatchString(".*executable file not found in.*", runtimeMsg); match { + if match, _ := regexp.MatchString(".*executable file not found in.*|.*no such file or directory.*", r); match { return errors.Wrapf(define.ErrOCIRuntimeNotFound, "%s", strings.Trim(runtimeMsg, "\n")) } return errors.Wrapf(define.ErrOCIRuntime, "%s", strings.Trim(runtimeMsg, "\n")) diff --git a/libpod/oci_linux.go b/libpod/oci_linux.go index 45365203e..1613c3e68 100644 --- a/libpod/oci_linux.go +++ b/libpod/oci_linux.go @@ -208,7 +208,7 @@ func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty } }() - runtimeDir, err := util.GetRootlessRuntimeDir() + runtimeDir, err := util.GetRuntimeDir() if err != nil { return -1, nil, err } @@ -437,7 +437,7 @@ func (r *OCIRuntime) stopContainer(ctr *Container, timeout uint) error { args = []string{"kill", "--all", ctr.ID(), "KILL"} } - runtimeDir, err := util.GetRootlessRuntimeDir() + runtimeDir, err := util.GetRuntimeDir() if err != nil { return err } @@ -487,7 +487,7 @@ func (r *OCIRuntime) execStopContainer(ctr *Container, timeout uint) error { if len(execSessions) == 0 { return nil } - runtimeDir, err := util.GetRootlessRuntimeDir() + runtimeDir, err := util.GetRuntimeDir() if err != nil { return err } diff --git a/libpod/options.go b/libpod/options.go index d2a67e38c..a7ddbec34 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1371,6 +1371,17 @@ func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption { } } +// WithHealthCheck adds the healthcheck to the container config +func WithHealthCheck(healthCheck *manifest.Schema2HealthConfig) CtrCreateOption { + return func(ctr *Container) error { + if ctr.valid { + return define.ErrCtrFinalized + } + ctr.config.HealthCheckConfig = healthCheck + return nil + } +} + // Volume Creation Options // WithVolumeName sets the name of the volume. @@ -1390,30 +1401,30 @@ func WithVolumeName(name string) VolumeCreateOption { } } -// WithVolumeLabels sets the labels of the volume. -func WithVolumeLabels(labels map[string]string) VolumeCreateOption { +// WithVolumeDriver sets the volume's driver. +// It is presently not implemented, but will be supported in a future Podman +// release. +func WithVolumeDriver(driver string) VolumeCreateOption { return func(volume *Volume) error { if volume.valid { return define.ErrVolumeFinalized } - volume.config.Labels = make(map[string]string) - for key, value := range labels { - volume.config.Labels[key] = value - } - - return nil + return define.ErrNotImplemented } } -// WithVolumeDriver sets the driver of the volume. -func WithVolumeDriver(driver string) VolumeCreateOption { +// WithVolumeLabels sets the labels of the volume. +func WithVolumeLabels(labels map[string]string) VolumeCreateOption { return func(volume *Volume) error { if volume.valid { return define.ErrVolumeFinalized } - volume.config.Driver = driver + volume.config.Labels = make(map[string]string) + for key, value := range labels { + volume.config.Labels[key] = value + } return nil } @@ -1700,14 +1711,3 @@ func WithInfraContainerPorts(bindings []ocicni.PortMapping) PodCreateOption { return nil } } - -// WithHealthCheck adds the healthcheck to the container config -func WithHealthCheck(healthCheck *manifest.Schema2HealthConfig) CtrCreateOption { - return func(ctr *Container) error { - if ctr.valid { - return define.ErrCtrFinalized - } - ctr.config.HealthCheckConfig = healthCheck - return nil - } -} diff --git a/libpod/runtime.go b/libpod/runtime.go index 2fa8dd424..cbbf667db 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -369,7 +369,7 @@ func SetXdgDirs() error { if runtimeDir == "" { var err error - runtimeDir, err = util.GetRootlessRuntimeDir() + runtimeDir, err = util.GetRuntimeDir() if err != nil { return err } @@ -395,11 +395,11 @@ func getDefaultTmpDir() (string, error) { return "/var/run/libpod", nil } - rootlessRuntimeDir, err := util.GetRootlessRuntimeDir() + runtimeDir, err := util.GetRuntimeDir() if err != nil { return "", err } - libpodRuntimeDir := filepath.Join(rootlessRuntimeDir, "libpod") + libpodRuntimeDir := filepath.Join(runtimeDir, "libpod") if err := os.Mkdir(libpodRuntimeDir, 0700|os.ModeSticky); err != nil { if !os.IsExist(err) { diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go index ac6fd02c3..84703787d 100644 --- a/libpod/runtime_volume_linux.go +++ b/libpod/runtime_volume_linux.go @@ -7,6 +7,7 @@ import ( "os" "path/filepath" "strings" + "time" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/events" @@ -42,14 +43,10 @@ func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption) if volume.config.Name == "" { volume.config.Name = stringid.GenerateNonCryptoID() } - // TODO: support for other volume drivers if volume.config.Driver == "" { volume.config.Driver = "local" } - // TODO: determine when the scope is global and set it to that - if volume.config.Scope == "" { - volume.config.Scope = "local" - } + volume.config.CreatedTime = time.Now() // Create the mountpoint of this volume volPathRoot := filepath.Join(r.config.VolumePath, volume.config.Name) diff --git a/libpod/volume.go b/libpod/volume.go index 9ed2ff087..74126b49b 100644 --- a/libpod/volume.go +++ b/libpod/volume.go @@ -1,5 +1,9 @@ package libpod +import ( + "time" +) + // Volume is the type used to create named volumes // TODO: all volumes should be created using this and the Volume API type Volume struct { @@ -15,10 +19,10 @@ type VolumeConfig struct { Name string `json:"name"` Labels map[string]string `json:"labels"` - MountPoint string `json:"mountPoint"` Driver string `json:"driver"` + MountPoint string `json:"mountPoint"` + CreatedTime time.Time `json:"createdAt,omitempty"` Options map[string]string `json:"options"` - Scope string `json:"scope"` IsCtrSpecific bool `json:"ctrSpecific"` UID int `json:"uid"` GID int `json:"gid"` @@ -29,6 +33,18 @@ func (v *Volume) Name() string { return v.config.Name } +// Driver retrieves the volume's driver. +func (v *Volume) Driver() string { + return v.config.Driver +} + +// Scope retrieves the volume's scope. +// Libpod does not implement volume scoping, and this is provided solely for +// Docker compatibility. It returns only "local". +func (v *Volume) Scope() string { + return "local" +} + // Labels returns the volume's labels func (v *Volume) Labels() map[string]string { labels := make(map[string]string) @@ -43,11 +59,6 @@ func (v *Volume) MountPoint() string { return v.config.MountPoint } -// Driver returns the volume's driver -func (v *Volume) Driver() string { - return v.config.Driver -} - // Options return the volume's options func (v *Volume) Options() map[string]string { options := make(map[string]string) @@ -58,14 +69,25 @@ func (v *Volume) Options() map[string]string { return options } -// Scope returns the scope of the volume -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 } + +// UID returns the UID the volume will be created as. +func (v *Volume) UID() int { + return v.config.UID +} + +// GID returns the GID the volume will be created as. +func (v *Volume) GID() int { + return v.config.GID +} + +// CreatedTime returns the time the volume was created at. It was not tracked +// for some time, so older volumes may not contain one. +func (v *Volume) CreatedTime() time.Time { + return v.config.CreatedTime +} diff --git a/libpod/volume_inspect.go b/libpod/volume_inspect.go new file mode 100644 index 000000000..87ed9d340 --- /dev/null +++ b/libpod/volume_inspect.go @@ -0,0 +1,70 @@ +package libpod + +import ( + "time" + + "github.com/containers/libpod/libpod/define" +) + +// InspectVolumeData is the output of Inspect() on a volume. It is matched to +// the format of 'docker volume inspect'. +type InspectVolumeData struct { + // Name is the name of the volume. + Name string `json:"Name"` + // Driver is the driver used to create the volume. + // This will be properly implemented in a future version. + Driver string `json:"Driver"` + // Mountpoint is the path on the host where the volume is mounted. + Mountpoint string `json:"Mountpoint"` + // CreatedAt is the date and time the volume was created at. This is not + // stored for older Libpod volumes; if so, it will be omitted. + CreatedAt time.Time `json:"CreatedAt,omitempty"` + // Status is presently unused and provided only for Docker compatibility. + // In the future it will be used to return information on the volume's + // current state. + Status map[string]string `json:"Status,omitempty"` + // Labels includes the volume's configured labels, key:value pairs that + // can be passed during volume creation to provide information for third + // party tools. + Labels map[string]string `json:"Labels"` + // Scope is unused and provided solely for Docker compatibility. It is + // unconditionally set to "local". + Scope string `json:"Scope"` + // Options is a set of options that were used when creating the volume. + // It is presently not used. + Options map[string]string `json:"Options"` + // UID is the UID that the volume was created with. + UID int `json:"UID,omitempty"` + // GID is the GID that the volume was created with. + GID int `json:"GID,omitempty"` + // ContainerSpecific indicates that the volume was created as part of a + // specific container, and will be removed when that container is + // removed. + ContainerSpecific bool `json:"ContainerSpecific,omitempty"` +} + +// Inspect provides detailed information about the configuration of the given +// volume. +func (v *Volume) Inspect() (*InspectVolumeData, error) { + if !v.valid { + return nil, define.ErrVolumeRemoved + } + + data := new(InspectVolumeData) + + data.Name = v.config.Name + data.Driver = v.config.Driver + data.Mountpoint = v.config.MountPoint + data.CreatedAt = v.config.CreatedTime + data.Labels = make(map[string]string) + for k, v := range v.config.Labels { + data.Labels[k] = v + } + data.Scope = v.Scope() + data.Options = make(map[string]string) + data.UID = v.config.UID + data.GID = v.config.GID + data.ContainerSpecific = v.config.IsCtrSpecific + + return data, nil +} |