098a44c07f
Finish the refactor which was partially completed with commit
34536c498d
, passing around IdentityMapping structs instead of pairs of
[]IDMap slices.
Existing code which uses []IDMap relies on zero-valued fields to be
valid, empty mappings. So in order to successfully finish the
refactoring without introducing bugs, their replacement therefore also
needs to have a useful zero value which represents an empty mapping.
Change IdentityMapping to be a pass-by-value type so that there are no
nil pointers to worry about.
The functionality provided by the deprecated NewIDMappingsFromMaps
function is required by unit tests to to construct arbitrary
IdentityMapping values. And the daemon will always need to access the
mappings to pass them to the Linux kernel. Accommodate these use cases
by exporting the struct fields instead. BuildKit currently depends on
the UIDs and GIDs methods so we cannot get rid of them yet.
Signed-off-by: Cory Snider <csnider@mirantis.com>
262 lines
6.3 KiB
Go
262 lines
6.3 KiB
Go
package graphdriver // import "github.com/docker/docker/daemon/graphdriver"
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/docker/docker/pkg/archive"
|
|
"github.com/docker/docker/pkg/containerfs"
|
|
"github.com/docker/docker/pkg/idtools"
|
|
"github.com/docker/docker/pkg/plugingetter"
|
|
"github.com/docker/docker/pkg/plugins"
|
|
)
|
|
|
|
type graphDriverProxy struct {
|
|
name string
|
|
p plugingetter.CompatPlugin
|
|
caps Capabilities
|
|
client *plugins.Client
|
|
}
|
|
|
|
type graphDriverRequest struct {
|
|
ID string `json:",omitempty"`
|
|
Parent string `json:",omitempty"`
|
|
MountLabel string `json:",omitempty"`
|
|
StorageOpt map[string]string `json:",omitempty"`
|
|
}
|
|
|
|
type graphDriverResponse struct {
|
|
Err string `json:",omitempty"`
|
|
Dir string `json:",omitempty"`
|
|
Exists bool `json:",omitempty"`
|
|
Status [][2]string `json:",omitempty"`
|
|
Changes []archive.Change `json:",omitempty"`
|
|
Size int64 `json:",omitempty"`
|
|
Metadata map[string]string `json:",omitempty"`
|
|
Capabilities Capabilities `json:",omitempty"`
|
|
}
|
|
|
|
type graphDriverInitRequest struct {
|
|
Home string
|
|
Opts []string `json:"Opts"`
|
|
idtools.IdentityMapping
|
|
}
|
|
|
|
func (d *graphDriverProxy) Init(home string, opts []string, idMap idtools.IdentityMapping) error {
|
|
if !d.p.IsV1() {
|
|
if cp, ok := d.p.(plugingetter.CountedPlugin); ok {
|
|
// always acquire here, it will be cleaned up on daemon shutdown
|
|
cp.Acquire()
|
|
}
|
|
}
|
|
args := &graphDriverInitRequest{
|
|
Home: home,
|
|
Opts: opts,
|
|
IdentityMapping: idMap,
|
|
}
|
|
var ret graphDriverResponse
|
|
if err := d.client.Call("GraphDriver.Init", args, &ret); err != nil {
|
|
return err
|
|
}
|
|
if ret.Err != "" {
|
|
return errors.New(ret.Err)
|
|
}
|
|
caps, err := d.fetchCaps()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
d.caps = caps
|
|
return nil
|
|
}
|
|
|
|
func (d *graphDriverProxy) fetchCaps() (Capabilities, error) {
|
|
args := &graphDriverRequest{}
|
|
var ret graphDriverResponse
|
|
if err := d.client.Call("GraphDriver.Capabilities", args, &ret); err != nil {
|
|
if !plugins.IsNotFound(err) {
|
|
return Capabilities{}, err
|
|
}
|
|
}
|
|
return ret.Capabilities, nil
|
|
}
|
|
|
|
func (d *graphDriverProxy) String() string {
|
|
return d.name
|
|
}
|
|
|
|
func (d *graphDriverProxy) Capabilities() Capabilities {
|
|
return d.caps
|
|
}
|
|
|
|
func (d *graphDriverProxy) CreateReadWrite(id, parent string, opts *CreateOpts) error {
|
|
return d.create("GraphDriver.CreateReadWrite", id, parent, opts)
|
|
}
|
|
|
|
func (d *graphDriverProxy) Create(id, parent string, opts *CreateOpts) error {
|
|
return d.create("GraphDriver.Create", id, parent, opts)
|
|
}
|
|
|
|
func (d *graphDriverProxy) create(method, id, parent string, opts *CreateOpts) error {
|
|
args := &graphDriverRequest{
|
|
ID: id,
|
|
Parent: parent,
|
|
}
|
|
if opts != nil {
|
|
args.MountLabel = opts.MountLabel
|
|
args.StorageOpt = opts.StorageOpt
|
|
}
|
|
var ret graphDriverResponse
|
|
if err := d.client.Call(method, args, &ret); err != nil {
|
|
return err
|
|
}
|
|
if ret.Err != "" {
|
|
return errors.New(ret.Err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *graphDriverProxy) Remove(id string) error {
|
|
args := &graphDriverRequest{ID: id}
|
|
var ret graphDriverResponse
|
|
if err := d.client.Call("GraphDriver.Remove", args, &ret); err != nil {
|
|
return err
|
|
}
|
|
if ret.Err != "" {
|
|
return errors.New(ret.Err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *graphDriverProxy) Get(id, mountLabel string) (containerfs.ContainerFS, error) {
|
|
args := &graphDriverRequest{
|
|
ID: id,
|
|
MountLabel: mountLabel,
|
|
}
|
|
var ret graphDriverResponse
|
|
if err := d.client.Call("GraphDriver.Get", args, &ret); err != nil {
|
|
return nil, err
|
|
}
|
|
var err error
|
|
if ret.Err != "" {
|
|
err = errors.New(ret.Err)
|
|
}
|
|
return containerfs.NewLocalContainerFS(d.p.ScopedPath(ret.Dir)), err
|
|
}
|
|
|
|
func (d *graphDriverProxy) Put(id string) error {
|
|
args := &graphDriverRequest{ID: id}
|
|
var ret graphDriverResponse
|
|
if err := d.client.Call("GraphDriver.Put", args, &ret); err != nil {
|
|
return err
|
|
}
|
|
if ret.Err != "" {
|
|
return errors.New(ret.Err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *graphDriverProxy) Exists(id string) bool {
|
|
args := &graphDriverRequest{ID: id}
|
|
var ret graphDriverResponse
|
|
if err := d.client.Call("GraphDriver.Exists", args, &ret); err != nil {
|
|
return false
|
|
}
|
|
return ret.Exists
|
|
}
|
|
|
|
func (d *graphDriverProxy) Status() [][2]string {
|
|
args := &graphDriverRequest{}
|
|
var ret graphDriverResponse
|
|
if err := d.client.Call("GraphDriver.Status", args, &ret); err != nil {
|
|
return nil
|
|
}
|
|
return ret.Status
|
|
}
|
|
|
|
func (d *graphDriverProxy) GetMetadata(id string) (map[string]string, error) {
|
|
args := &graphDriverRequest{
|
|
ID: id,
|
|
}
|
|
var ret graphDriverResponse
|
|
if err := d.client.Call("GraphDriver.GetMetadata", args, &ret); err != nil {
|
|
return nil, err
|
|
}
|
|
if ret.Err != "" {
|
|
return nil, errors.New(ret.Err)
|
|
}
|
|
return ret.Metadata, nil
|
|
}
|
|
|
|
func (d *graphDriverProxy) Cleanup() error {
|
|
if !d.p.IsV1() {
|
|
if cp, ok := d.p.(plugingetter.CountedPlugin); ok {
|
|
// always release
|
|
defer cp.Release()
|
|
}
|
|
}
|
|
|
|
args := &graphDriverRequest{}
|
|
var ret graphDriverResponse
|
|
if err := d.client.Call("GraphDriver.Cleanup", args, &ret); err != nil {
|
|
return nil
|
|
}
|
|
if ret.Err != "" {
|
|
return errors.New(ret.Err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *graphDriverProxy) Diff(id, parent string) (io.ReadCloser, error) {
|
|
args := &graphDriverRequest{
|
|
ID: id,
|
|
Parent: parent,
|
|
}
|
|
body, err := d.client.Stream("GraphDriver.Diff", args)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return body, nil
|
|
}
|
|
|
|
func (d *graphDriverProxy) Changes(id, parent string) ([]archive.Change, error) {
|
|
args := &graphDriverRequest{
|
|
ID: id,
|
|
Parent: parent,
|
|
}
|
|
var ret graphDriverResponse
|
|
if err := d.client.Call("GraphDriver.Changes", args, &ret); err != nil {
|
|
return nil, err
|
|
}
|
|
if ret.Err != "" {
|
|
return nil, errors.New(ret.Err)
|
|
}
|
|
|
|
return ret.Changes, nil
|
|
}
|
|
|
|
func (d *graphDriverProxy) ApplyDiff(id, parent string, diff io.Reader) (int64, error) {
|
|
var ret graphDriverResponse
|
|
if err := d.client.SendFile(fmt.Sprintf("GraphDriver.ApplyDiff?id=%s&parent=%s", id, parent), diff, &ret); err != nil {
|
|
return -1, err
|
|
}
|
|
if ret.Err != "" {
|
|
return -1, errors.New(ret.Err)
|
|
}
|
|
return ret.Size, nil
|
|
}
|
|
|
|
func (d *graphDriverProxy) DiffSize(id, parent string) (int64, error) {
|
|
args := &graphDriverRequest{
|
|
ID: id,
|
|
Parent: parent,
|
|
}
|
|
var ret graphDriverResponse
|
|
if err := d.client.Call("GraphDriver.DiffSize", args, &ret); err != nil {
|
|
return -1, err
|
|
}
|
|
if ret.Err != "" {
|
|
return -1, errors.New(ret.Err)
|
|
}
|
|
return ret.Size, nil
|
|
}
|