diff options
34 files changed, 891 insertions, 137 deletions
diff --git a/cmd/podman/formats/formats.go b/cmd/podman/formats/formats.go index 3da0ea385..c454c39bd 100644 --- a/cmd/podman/formats/formats.go +++ b/cmd/podman/formats/formats.go @@ -20,6 +20,8 @@ const ( JSONString = "json" // IDString const to save on duplicates for Go templates IDString = "{{.ID}}" + + parsingErrorStr = "Template parsing error" ) // Writer interface for outputs @@ -96,7 +98,7 @@ func (t StdoutTemplateArray) Out() error { t.Template = strings.Replace(strings.TrimSpace(t.Template[5:]), " ", "\t", -1) headerTmpl, err := template.New("header").Funcs(headerFunctions).Parse(t.Template) if err != nil { - return errors.Wrapf(err, "Template parsing error") + return errors.Wrapf(err, parsingErrorStr) } err = headerTmpl.Execute(w, t.Fields) if err != nil { @@ -107,13 +109,12 @@ func (t StdoutTemplateArray) Out() error { t.Template = strings.Replace(t.Template, " ", "\t", -1) tmpl, err := template.New("image").Funcs(basicFunctions).Parse(t.Template) if err != nil { - return errors.Wrapf(err, "Template parsing error") + return errors.Wrapf(err, parsingErrorStr) } - for i, img := range t.Output { + for i, raw := range t.Output { basicTmpl := tmpl.Funcs(basicFunctions) - err = basicTmpl.Execute(w, img) - if err != nil { - return err + if err := basicTmpl.Execute(w, raw); err != nil { + return errors.Wrapf(err, parsingErrorStr) } if i != len(t.Output)-1 { fmt.Fprintln(w, "") diff --git a/cmd/podman/inspect.go b/cmd/podman/inspect.go index 6ffcde55f..2f1e97c6c 100644 --- a/cmd/podman/inspect.go +++ b/cmd/podman/inspect.go @@ -87,6 +87,9 @@ func inspectCmd(c *cli.Context) error { } inspectedObjects, iterateErr := iterateInput(getContext(), c, args, runtime, inspectType) + if iterateErr != nil { + return iterateErr + } var out formats.Writer if outputFormat != "" && outputFormat != formats.JSONString { @@ -97,8 +100,7 @@ func inspectCmd(c *cli.Context) error { out = formats.JSONStructArray{Output: inspectedObjects} } - formats.Writer(out).Out() - return iterateErr + return formats.Writer(out).Out() } // func iterateInput iterates the images|containers the user has requested and returns the inspect data and error diff --git a/install.md b/install.md index 5ee5bed11..c5268c04d 100644 --- a/install.md +++ b/install.md @@ -29,6 +29,10 @@ sudo emerge app-emulation/libpod sudo zypper install podman ``` +#### [openSUSE Kubic](https://kubic.opensuse.org) + +Built-in, no need to install + #### [RHEL7](https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux) Subscribe, then enable Extras channel and install podman. diff --git a/libpod/adapter/client.go b/libpod/adapter/client.go index 383c242c9..b3bb9acae 100644 --- a/libpod/adapter/client.go +++ b/libpod/adapter/client.go @@ -3,12 +3,32 @@ package adapter import ( + "os" + + "github.com/sirupsen/logrus" "github.com/varlink/go/varlink" ) +// DefaultAddress is the default address of the varlink socket +const DefaultAddress = "unix:/run/podman/io.podman" + // Connect provides a varlink connection func (r RemoteRuntime) Connect() (*varlink.Connection, error) { - connection, err := varlink.NewConnection("unix:/run/podman/io.podman") + var err error + var connection *varlink.Connection + if bridge := os.Getenv("PODMAN_VARLINK_BRIDGE"); bridge != "" { + logrus.Infof("Connecting with varlink bridge") + logrus.Debugf("%s", bridge) + connection, err = varlink.NewBridge(bridge) + } else { + address := os.Getenv("PODMAN_VARLINK_ADDRESS") + if address == "" { + address = DefaultAddress + } + logrus.Infof("Connecting with varlink address") + logrus.Debugf("%s", address) + connection, err = varlink.NewConnection(address) + } if err != nil { return nil, err } diff --git a/libpod/container.go b/libpod/container.go index 95f7a2972..b5f6a29ba 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -415,14 +415,15 @@ func (c *Container) Spec() *spec.Spec { // config does not exist (e.g., because the container was never started) return // the spec from the config. func (c *Container) specFromState() (*spec.Spec, error) { - spec := c.config.Spec + returnSpec := c.config.Spec if f, err := os.Open(c.state.ConfigPath); err == nil { + returnSpec = new(spec.Spec) content, err := ioutil.ReadAll(f) if err != nil { return nil, errors.Wrapf(err, "error reading container config") } - if err := json.Unmarshal([]byte(content), &spec); err != nil { + if err := json.Unmarshal([]byte(content), &returnSpec); err != nil { return nil, errors.Wrapf(err, "error unmarshalling container config") } } else { @@ -432,7 +433,7 @@ func (c *Container) specFromState() (*spec.Spec, error) { } } - return spec, nil + return returnSpec, nil } // ID returns the container's ID diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 9ef0223f2..46105af4a 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -376,6 +376,10 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint } func blockAccessToKernelFilesystems(config *CreateConfig, g *generate.Generator) { + if config.PidMode.IsHost() && rootless.IsRootless() { + return + } + if !config.Privileged { for _, mp := range []string{ "/proc/acpi", diff --git a/test/e2e/rootless_test.go b/test/e2e/rootless_test.go index daf8b8c32..2b84d34c9 100644 --- a/test/e2e/rootless_test.go +++ b/test/e2e/rootless_test.go @@ -276,6 +276,10 @@ var _ = Describe("Podman rootless", func() { runRootlessHelper([]string{"--net", "host"}) }) + It("podman rootless rootfs --pid host", func() { + runRootlessHelper([]string{"--pid", "host"}) + }) + It("podman rootless rootfs --privileged", func() { runRootlessHelper([]string{"--privileged"}) }) diff --git a/vendor.conf b/vendor.conf index 476150a53..9c9d41a0d 100644 --- a/vendor.conf +++ b/vendor.conf @@ -16,7 +16,7 @@ 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.3 -github.com/containers/storage v1.6 +github.com/containers/storage v1.7 github.com/containers/psgo v1.1 github.com/coreos/go-systemd v14 github.com/cri-o/ocicni 2d2983e40c242322a56c22a903785e7f83eb378c @@ -90,7 +90,7 @@ k8s.io/api kubernetes-1.10.13-beta.0 https://github.com/kubernetes/api k8s.io/apimachinery kubernetes-1.10.13-beta.0 https://github.com/kubernetes/apimachinery k8s.io/client-go kubernetes-1.10.13-beta.0 https://github.com/kubernetes/client-go github.com/mrunalp/fileutils 7d4729fb36185a7c1719923406c9d40e54fb93c7 -github.com/varlink/go e9fdc57f40123518ac513eb3443e50625ad6b434 +github.com/varlink/go 92687ab4eb68d99e43b1f5b93477ad76bb54f811 github.com/containers/buildah e7ca330f923701dba8859f5c014d0a9a3f7f0a49 # TODO: Gotty has not been updated since 2012. Can we find replacement? github.com/Nvveen/Gotty cd527374f1e5bff4938207604a14f2e38a9cf512 diff --git a/vendor/github.com/containers/storage/containers_ffjson.go b/vendor/github.com/containers/storage/containers_ffjson.go index aef6becfe..40b912bb3 100644 --- a/vendor/github.com/containers/storage/containers_ffjson.go +++ b/vendor/github.com/containers/storage/containers_ffjson.go @@ -1,5 +1,5 @@ // Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT. -// source: containers.go +// source: ./containers.go package storage diff --git a/vendor/github.com/containers/storage/drivers/aufs/aufs.go b/vendor/github.com/containers/storage/drivers/aufs/aufs.go index ca69816be..e821bc0c5 100644 --- a/vendor/github.com/containers/storage/drivers/aufs/aufs.go +++ b/vendor/github.com/containers/storage/drivers/aufs/aufs.go @@ -253,6 +253,11 @@ func (a *Driver) AdditionalImageStores() []string { return nil } +// CreateFromTemplate creates a layer with the same contents and parent as another layer. +func (a *Driver) CreateFromTemplate(id, template string, templateIDMappings *idtools.IDMappings, parent string, parentIDMappings *idtools.IDMappings, opts *graphdriver.CreateOpts, readWrite bool) error { + return graphdriver.NaiveCreateFromTemplate(a, id, template, templateIDMappings, parent, parentIDMappings, opts, readWrite) +} + // CreateReadWrite creates a layer that is writable for use as a container // file system. func (a *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error { diff --git a/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go b/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go index 567cda9d3..30254d9fb 100644 --- a/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go +++ b/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go @@ -490,6 +490,11 @@ func (d *Driver) quotasDirID(id string) string { return path.Join(d.quotasDir(), id) } +// CreateFromTemplate creates a layer with the same contents and parent as another layer. +func (d *Driver) CreateFromTemplate(id, template string, templateIDMappings *idtools.IDMappings, parent string, parentIDMappings *idtools.IDMappings, opts *graphdriver.CreateOpts, readWrite bool) error { + return d.Create(id, template, opts) +} + // CreateReadWrite creates a layer that is writable for use as a container // file system. func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error { diff --git a/vendor/github.com/containers/storage/drivers/devmapper/driver.go b/vendor/github.com/containers/storage/drivers/devmapper/driver.go index 39a4fbe2c..13677c93a 100644 --- a/vendor/github.com/containers/storage/drivers/devmapper/driver.go +++ b/vendor/github.com/containers/storage/drivers/devmapper/driver.go @@ -123,6 +123,11 @@ func (d *Driver) Cleanup() error { return err } +// CreateFromTemplate creates a layer with the same contents and parent as another layer. +func (d *Driver) CreateFromTemplate(id, template string, templateIDMappings *idtools.IDMappings, parent string, parentIDMappings *idtools.IDMappings, opts *graphdriver.CreateOpts, readWrite bool) error { + return d.Create(id, template, opts) +} + // CreateReadWrite creates a layer that is writable for use as a container // file system. func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error { diff --git a/vendor/github.com/containers/storage/drivers/driver.go b/vendor/github.com/containers/storage/drivers/driver.go index 476b55160..dda172574 100644 --- a/vendor/github.com/containers/storage/drivers/driver.go +++ b/vendor/github.com/containers/storage/drivers/driver.go @@ -72,6 +72,9 @@ type ProtoDriver interface { // specified id and parent and options passed in opts. Parent // may be "" and opts may be nil. Create(id, parent string, opts *CreateOpts) error + // CreateFromTemplate creates a new filesystem layer with the specified id + // and parent, with contents identical to the specified template layer. + CreateFromTemplate(id, template string, templateIDMappings *idtools.IDMappings, parent string, parentIDMappings *idtools.IDMappings, opts *CreateOpts, readWrite bool) error // Remove attempts to remove the filesystem layer with this id. Remove(id string) error // Get returns the mountpoint for the layered filesystem referred diff --git a/vendor/github.com/containers/storage/drivers/overlay/check.go b/vendor/github.com/containers/storage/drivers/overlay/check.go index 590d517fa..a566e4afd 100644 --- a/vendor/github.com/containers/storage/drivers/overlay/check.go +++ b/vendor/github.com/containers/storage/drivers/overlay/check.go @@ -10,6 +10,8 @@ import ( "path/filepath" "syscall" + "github.com/containers/storage/pkg/ioutils" + "github.com/containers/storage/pkg/mount" "github.com/containers/storage/pkg/system" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -57,10 +59,11 @@ func doesSupportNativeDiff(d, mountOpts string) error { } opts := fmt.Sprintf("lowerdir=%s:%s,upperdir=%s,workdir=%s", path.Join(td, "l2"), path.Join(td, "l1"), path.Join(td, "l3"), path.Join(td, "work")) - if mountOpts != "" { - opts = fmt.Sprintf("%s,%s", opts, mountOpts) + flags, data := mount.ParseOptions(mountOpts) + if data != "" { + opts = fmt.Sprintf("%s,%s", opts, data) } - if err := unix.Mount("overlay", filepath.Join(td, "merged"), "overlay", 0, opts); err != nil { + if err := unix.Mount("overlay", filepath.Join(td, "merged"), "overlay", uintptr(flags), opts); err != nil { return errors.Wrap(err, "failed to mount overlay") } defer func() { @@ -103,3 +106,60 @@ func doesSupportNativeDiff(d, mountOpts string) error { return nil } + +// doesMetacopy checks if the filesystem is going to optimize changes to +// metadata by using nodes marked with an "overlay.metacopy" attribute to avoid +// copying up a file from a lower layer unless/until its contents are being +// modified +func doesMetacopy(d, mountOpts string) (bool, error) { + td, err := ioutil.TempDir(d, "metacopy-check") + if err != nil { + return false, err + } + defer func() { + if err := os.RemoveAll(td); err != nil { + logrus.Warnf("Failed to remove check directory %v: %v", td, err) + } + }() + + // Make directories l1, l2, work, merged + if err := os.MkdirAll(filepath.Join(td, "l1"), 0755); err != nil { + return false, err + } + if err := ioutils.AtomicWriteFile(filepath.Join(td, "l1", "f"), []byte{0xff}, 0700); err != nil { + return false, err + } + if err := os.MkdirAll(filepath.Join(td, "l2"), 0755); err != nil { + return false, err + } + if err := os.Mkdir(filepath.Join(td, "work"), 0755); err != nil { + return false, err + } + if err := os.Mkdir(filepath.Join(td, "merged"), 0755); err != nil { + return false, err + } + // Mount using the mandatory options and configured options + opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", path.Join(td, "l1"), path.Join(td, "l2"), path.Join(td, "work")) + flags, data := mount.ParseOptions(mountOpts) + if data != "" { + opts = fmt.Sprintf("%s,%s", opts, data) + } + if err := unix.Mount("overlay", filepath.Join(td, "merged"), "overlay", uintptr(flags), opts); err != nil { + return false, errors.Wrap(err, "failed to mount overlay for metacopy check") + } + defer func() { + if err := unix.Unmount(filepath.Join(td, "merged"), 0); err != nil { + logrus.Warnf("Failed to unmount check directory %v: %v", filepath.Join(td, "merged"), err) + } + }() + // Make a change that only impacts the inode, and check if the pulled-up copy is marked + // as a metadata-only copy + if err := os.Chmod(filepath.Join(td, "merged", "f"), 0600); err != nil { + return false, errors.Wrap(err, "error changing permissions on file for metacopy check") + } + metacopy, err := system.Lgetxattr(filepath.Join(td, "l2", "f"), "trusted.overlay.metacopy") + if err != nil { + return false, errors.Wrap(err, "metacopy flag was not set on file in upper layer") + } + return metacopy != nil, nil +} diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go index 06d58db38..3e8daf23c 100644 --- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go +++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go @@ -85,13 +85,12 @@ const ( ) type overlayOptions struct { - overrideKernelCheck bool - imageStores []string - quota quota.Quota - mountProgram string - ostreeRepo string - skipMountHome bool - mountOptions string + imageStores []string + quota quota.Quota + mountProgram string + ostreeRepo string + skipMountHome bool + mountOptions string } // Driver contains information about the home directory and the list of active mounts that are created using this driver. @@ -105,6 +104,7 @@ type Driver struct { options overlayOptions naiveDiff graphdriver.DiffDriver supportsDType bool + usingMetacopy bool locker *locker.Locker convert map[string]bool } @@ -174,6 +174,18 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap } } + usingMetacopy, err := doesMetacopy(home, opts.mountOptions) + if err == nil { + if usingMetacopy { + logrus.Debugf("overlay test mount indicated that metacopy is being used") + } else { + logrus.Debugf("overlay test mount indicated that metacopy is not being used") + } + } else { + logrus.Warnf("overlay test mount did not indicate whether or not metacopy is being used: %v", err) + return nil, err + } + if !opts.skipMountHome { if err := mount.MakePrivate(home); err != nil { return nil, err @@ -193,6 +205,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap gidMaps: gidMaps, ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)), supportsDType: supportsDType, + usingMetacopy: usingMetacopy, locker: locker.New(), options: *opts, convert: make(map[string]bool), @@ -212,7 +225,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap return nil, fmt.Errorf("Storage option overlay.size only supported for backingFS XFS. Found %v", backingFs) } - logrus.Debugf("backingFs=%s, projectQuotaSupported=%v, useNativeDiff=%v", backingFs, projectQuotaSupported, !d.useNaiveDiff()) + logrus.Debugf("backingFs=%s, projectQuotaSupported=%v, useNativeDiff=%v, usingMetacopy=%v", backingFs, projectQuotaSupported, !d.useNaiveDiff(), d.usingMetacopy) return d, nil } @@ -226,12 +239,6 @@ func parseOptions(options []string) (*overlayOptions, error) { } key = strings.ToLower(key) switch key { - case ".override_kernel_check", "overlay.override_kernel_check", "overlay2.override_kernel_check": - logrus.Debugf("overlay: override_kernelcheck=%s", val) - o.overrideKernelCheck, err = strconv.ParseBool(val) - if err != nil { - return nil, err - } case ".mountopt", "overlay.mountopt", "overlay2.mountopt": o.mountOptions = val case ".size", "overlay.size", "overlay2.size": @@ -375,6 +382,7 @@ func (d *Driver) Status() [][2]string { {"Backing Filesystem", backingFs}, {"Supports d_type", strconv.FormatBool(d.supportsDType)}, {"Native Overlay Diff", strconv.FormatBool(!d.useNaiveDiff())}, + {"Using metacopy", strconv.FormatBool(d.usingMetacopy)}, } } @@ -410,6 +418,14 @@ func (d *Driver) Cleanup() error { return mount.Unmount(d.home) } +// CreateFromTemplate creates a layer with the same contents and parent as another layer. +func (d *Driver) CreateFromTemplate(id, template string, templateIDMappings *idtools.IDMappings, parent string, parentIDMappings *idtools.IDMappings, opts *graphdriver.CreateOpts, readWrite bool) error { + if readWrite { + return d.CreateReadWrite(id, template, opts) + } + return d.Create(id, template, opts) +} + // CreateReadWrite creates a layer that is writable for use as a container // file system. func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error { diff --git a/vendor/github.com/containers/storage/drivers/template.go b/vendor/github.com/containers/storage/drivers/template.go new file mode 100644 index 000000000..dfcbffb83 --- /dev/null +++ b/vendor/github.com/containers/storage/drivers/template.go @@ -0,0 +1,45 @@ +package graphdriver + +import ( + "github.com/sirupsen/logrus" + + "github.com/containers/storage/pkg/idtools" +) + +// TemplateDriver is just barely enough of a driver that we can implement a +// naive version of CreateFromTemplate on top of it. +type TemplateDriver interface { + DiffDriver + CreateReadWrite(id, parent string, opts *CreateOpts) error + Create(id, parent string, opts *CreateOpts) error + Remove(id string) error +} + +// CreateFromTemplate creates a layer with the same contents and parent as +// another layer. Internally, it may even depend on that other layer +// continuing to exist, as if it were actually a child of the child layer. +func NaiveCreateFromTemplate(d TemplateDriver, id, template string, templateIDMappings *idtools.IDMappings, parent string, parentIDMappings *idtools.IDMappings, opts *CreateOpts, readWrite bool) error { + var err error + if readWrite { + err = d.CreateReadWrite(id, parent, opts) + } else { + err = d.Create(id, parent, opts) + } + if err != nil { + return err + } + diff, err := d.Diff(template, templateIDMappings, parent, parentIDMappings, opts.MountLabel) + if err != nil { + if err2 := d.Remove(id); err2 != nil { + logrus.Errorf("error removing layer %q: %v", id, err2) + } + return err + } + if _, err = d.ApplyDiff(id, templateIDMappings, parent, opts.MountLabel, diff); err != nil { + if err2 := d.Remove(id); err2 != nil { + logrus.Errorf("error removing layer %q: %v", id, err2) + } + return err + } + return nil +} diff --git a/vendor/github.com/containers/storage/drivers/vfs/driver.go b/vendor/github.com/containers/storage/drivers/vfs/driver.go index f7f3c75ba..5941ccc17 100644 --- a/vendor/github.com/containers/storage/drivers/vfs/driver.go +++ b/vendor/github.com/containers/storage/drivers/vfs/driver.go @@ -99,6 +99,14 @@ func (d *Driver) Cleanup() error { return nil } +// CreateFromTemplate creates a layer with the same contents and parent as another layer. +func (d *Driver) CreateFromTemplate(id, template string, templateIDMappings *idtools.IDMappings, parent string, parentIDMappings *idtools.IDMappings, opts *graphdriver.CreateOpts, readWrite bool) error { + if readWrite { + return d.CreateReadWrite(id, template, opts) + } + return d.Create(id, template, opts) +} + // CreateReadWrite creates a layer that is writable for use as a container // file system. func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error { diff --git a/vendor/github.com/containers/storage/drivers/windows/windows.go b/vendor/github.com/containers/storage/drivers/windows/windows.go index c6d86a4ab..c7df1c1fe 100644 --- a/vendor/github.com/containers/storage/drivers/windows/windows.go +++ b/vendor/github.com/containers/storage/drivers/windows/windows.go @@ -185,6 +185,11 @@ func (d *Driver) Exists(id string) bool { return result } +// CreateFromTemplate creates a layer with the same contents and parent as another layer. +func (d *Driver) CreateFromTemplate(id, template string, templateIDMappings *idtools.IDMappings, parent string, parentIDMappings *idtools.IDMappings, opts *graphdriver.CreateOpts, readWrite bool) error { + return graphdriver.NaiveCreateFromTemplate(d, id, template, templateIDMappings, parent, parentIDMappings, opts, readWrite) +} + // CreateReadWrite creates a layer that is writable for use as a container // file system. func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error { diff --git a/vendor/github.com/containers/storage/drivers/zfs/zfs.go b/vendor/github.com/containers/storage/drivers/zfs/zfs.go index 69b143c54..eaa9e8bc5 100644 --- a/vendor/github.com/containers/storage/drivers/zfs/zfs.go +++ b/vendor/github.com/containers/storage/drivers/zfs/zfs.go @@ -259,6 +259,11 @@ func (d *Driver) mountPath(id string) string { return path.Join(d.options.mountPath, "graph", getMountpoint(id)) } +// CreateFromTemplate creates a layer with the same contents and parent as another layer. +func (d *Driver) CreateFromTemplate(id, template string, templateIDMappings *idtools.IDMappings, parent string, parentIDMappings *idtools.IDMappings, opts *graphdriver.CreateOpts, readWrite bool) error { + return d.Create(id, template, opts) +} + // CreateReadWrite creates a layer that is writable for use as a container // file system. func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error { diff --git a/vendor/github.com/containers/storage/images.go b/vendor/github.com/containers/storage/images.go index b10501b08..d99842534 100644 --- a/vendor/github.com/containers/storage/images.go +++ b/vendor/github.com/containers/storage/images.go @@ -42,7 +42,9 @@ type Image struct { // MappedTopLayers are the IDs of alternate versions of the top layer // which have the same contents and parent, and which differ from - // TopLayer only in which ID mappings they use. + // TopLayer only in which ID mappings they use. When the image is + // to be removed, they should be removed before the TopLayer, as the + // graph driver may depend on that. MappedTopLayers []string `json:"mapped-layers,omitempty"` // Metadata is data we keep for the convenience of the caller. It is not diff --git a/vendor/github.com/containers/storage/images_ffjson.go b/vendor/github.com/containers/storage/images_ffjson.go index 6b40ebd59..539acfe93 100644 --- a/vendor/github.com/containers/storage/images_ffjson.go +++ b/vendor/github.com/containers/storage/images_ffjson.go @@ -1,5 +1,5 @@ // Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT. -// source: images.go +// source: ./images.go package storage diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go index 299d2f818..cdc3cbba9 100644 --- a/vendor/github.com/containers/storage/layers.go +++ b/vendor/github.com/containers/storage/layers.go @@ -551,9 +551,20 @@ func (r *layerStore) Put(id string, parentLayer *Layer, names []string, mountLab } } parent := "" - var parentMappings *idtools.IDMappings if parentLayer != nil { parent = parentLayer.ID + } + var parentMappings, templateIDMappings, oldMappings *idtools.IDMappings + if moreOptions.TemplateLayer != "" { + templateLayer, ok := r.lookup(moreOptions.TemplateLayer) + if !ok { + return nil, -1, ErrLayerUnknown + } + templateIDMappings = idtools.NewIDMappingsFromMaps(templateLayer.UIDMap, templateLayer.GIDMap) + } else { + templateIDMappings = &idtools.IDMappings{} + } + if parentLayer != nil { parentMappings = idtools.NewIDMappingsFromMaps(parentLayer.UIDMap, parentLayer.GIDMap) } else { parentMappings = &idtools.IDMappings{} @@ -566,23 +577,34 @@ func (r *layerStore) Put(id string, parentLayer *Layer, names []string, mountLab MountLabel: mountLabel, StorageOpt: options, } - if writeable { - if err = r.driver.CreateReadWrite(id, parent, &opts); err != nil { + if moreOptions.TemplateLayer != "" { + if err = r.driver.CreateFromTemplate(id, moreOptions.TemplateLayer, templateIDMappings, parent, parentMappings, &opts, writeable); err != nil { if id != "" { - return nil, -1, errors.Wrapf(err, "error creating read-write layer with ID %q", id) + return nil, -1, errors.Wrapf(err, "error creating copy of template layer %q with ID %q", moreOptions.TemplateLayer, id) } - return nil, -1, errors.Wrapf(err, "error creating read-write layer") + return nil, -1, errors.Wrapf(err, "error creating copy of template layer %q", moreOptions.TemplateLayer) } + oldMappings = templateIDMappings } else { - if err = r.driver.Create(id, parent, &opts); err != nil { - if id != "" { - return nil, -1, errors.Wrapf(err, "error creating layer with ID %q", id) + if writeable { + if err = r.driver.CreateReadWrite(id, parent, &opts); err != nil { + if id != "" { + return nil, -1, errors.Wrapf(err, "error creating read-write layer with ID %q", id) + } + return nil, -1, errors.Wrapf(err, "error creating read-write layer") + } + } else { + if err = r.driver.Create(id, parent, &opts); err != nil { + if id != "" { + return nil, -1, errors.Wrapf(err, "error creating layer with ID %q", id) + } + return nil, -1, errors.Wrapf(err, "error creating layer") } - return nil, -1, errors.Wrapf(err, "error creating layer") } + oldMappings = parentMappings } - if !reflect.DeepEqual(parentMappings.UIDs(), idMappings.UIDs()) || !reflect.DeepEqual(parentMappings.GIDs(), idMappings.GIDs()) { - if err = r.driver.UpdateLayerIDMap(id, parentMappings, idMappings, mountLabel); err != nil { + if !reflect.DeepEqual(oldMappings.UIDs(), idMappings.UIDs()) || !reflect.DeepEqual(oldMappings.GIDs(), idMappings.GIDs()) { + if err = r.driver.UpdateLayerIDMap(id, oldMappings, idMappings, mountLabel); err != nil { // We don't have a record of this layer, but at least // try to clean it up underneath us. r.driver.Remove(id) diff --git a/vendor/github.com/containers/storage/layers_ffjson.go b/vendor/github.com/containers/storage/layers_ffjson.go index 125b5d8c9..09b5d0f33 100644 --- a/vendor/github.com/containers/storage/layers_ffjson.go +++ b/vendor/github.com/containers/storage/layers_ffjson.go @@ -1,5 +1,5 @@ // Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT. -// source: layers.go +// source: ./layers.go package storage diff --git a/vendor/github.com/containers/storage/pkg/archive/example_changes.go b/vendor/github.com/containers/storage/pkg/archive/example_changes.go new file mode 100644 index 000000000..70f9c5564 --- /dev/null +++ b/vendor/github.com/containers/storage/pkg/archive/example_changes.go @@ -0,0 +1,97 @@ +// +build ignore + +// Simple tool to create an archive stream from an old and new directory +// +// By default it will stream the comparison of two temporary directories with junk files +package main + +import ( + "flag" + "fmt" + "io" + "io/ioutil" + "os" + "path" + + "github.com/containers/storage/pkg/archive" + "github.com/sirupsen/logrus" +) + +var ( + flDebug = flag.Bool("D", false, "debugging output") + flNewDir = flag.String("newdir", "", "") + flOldDir = flag.String("olddir", "", "") + log = logrus.New() +) + +func main() { + flag.Usage = func() { + fmt.Println("Produce a tar from comparing two directory paths. By default a demo tar is created of around 200 files (including hardlinks)") + fmt.Printf("%s [OPTIONS]\n", os.Args[0]) + flag.PrintDefaults() + } + flag.Parse() + log.Out = os.Stderr + if (len(os.Getenv("DEBUG")) > 0) || *flDebug { + logrus.SetLevel(logrus.DebugLevel) + } + var newDir, oldDir string + + if len(*flNewDir) == 0 { + var err error + newDir, err = ioutil.TempDir("", "storage-test-newDir") + if err != nil { + log.Fatal(err) + } + defer os.RemoveAll(newDir) + if _, err := prepareUntarSourceDirectory(100, newDir, true); err != nil { + log.Fatal(err) + } + } else { + newDir = *flNewDir + } + + if len(*flOldDir) == 0 { + oldDir, err := ioutil.TempDir("", "storage-test-oldDir") + if err != nil { + log.Fatal(err) + } + defer os.RemoveAll(oldDir) + } else { + oldDir = *flOldDir + } + + changes, err := archive.ChangesDirs(newDir, oldDir) + if err != nil { + log.Fatal(err) + } + + a, err := archive.ExportChanges(newDir, changes) + if err != nil { + log.Fatal(err) + } + defer a.Close() + + i, err := io.Copy(os.Stdout, a) + if err != nil && err != io.EOF { + log.Fatal(err) + } + fmt.Fprintf(os.Stderr, "wrote archive of %d bytes", i) +} + +func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) { + fileData := []byte("fooo") + for n := 0; n < numberOfFiles; n++ { + fileName := fmt.Sprintf("file-%d", n) + if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil { + return 0, err + } + if makeLinks { + if err := os.Link(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil { + return 0, err + } + } + } + totalSize := numberOfFiles * len(fileData) + return totalSize, nil +} diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go index 5877c3b06..3fe305cc1 100644 --- a/vendor/github.com/containers/storage/store.go +++ b/vendor/github.com/containers/storage/store.go @@ -482,6 +482,10 @@ type LayerOptions struct { // inherit settings from its parent layer or, if it has no parent // layer, the Store object. IDMappingOptions + // TemplateLayer is the ID of a layer whose contents will be used to + // initialize this layer. If set, it should be a child of the layer + // which we want to use as the parent of the new layer. + TemplateLayer string } // ImageOptions is used for passing options to a Store's CreateImage() method. @@ -973,7 +977,7 @@ func (s *store) CreateImage(id string, names []string, layer, metadata string, o return ristore.Create(id, names, layer, metadata, creationDate, options.Digest) } -func (s *store) imageTopLayerForMapping(image *Image, ristore ROImageStore, readWrite bool, rlstore LayerStore, lstores []ROLayerStore, options IDMappingOptions) (*Layer, error) { +func (s *store) imageTopLayerForMapping(image *Image, ristore ROImageStore, createMappedLayer bool, rlstore LayerStore, lstores []ROLayerStore, options IDMappingOptions) (*Layer, error) { layerMatchesMappingOptions := func(layer *Layer, options IDMappingOptions) bool { // If the driver supports shifting and the layer has no mappings, we can use it. if s.graphDriver.SupportsShifting() && len(layer.UIDMap) == 0 && len(layer.GIDMap) == 0 { @@ -994,7 +998,6 @@ func (s *store) imageTopLayerForMapping(image *Image, ristore ROImageStore, read return reflect.DeepEqual(layer.UIDMap, options.UIDMap) && reflect.DeepEqual(layer.GIDMap, options.GIDMap) } var layer, parentLayer *Layer - var layerHomeStore ROLayerStore // Locate the image's top layer and its parent, if it has one. for _, store := range append([]ROLayerStore{rlstore}, lstores...) { if store != rlstore { @@ -1027,7 +1030,6 @@ func (s *store) imageTopLayerForMapping(image *Image, ristore ROImageStore, read if layer == nil { layer = cLayer parentLayer = cParentLayer - layerHomeStore = store } } } @@ -1037,27 +1039,25 @@ func (s *store) imageTopLayerForMapping(image *Image, ristore ROImageStore, read } // The top layer's mappings don't match the ones we want, but it's in a read-only // image store, so we can't create and add a mapped copy of the layer to the image. - if !readWrite { + // We'll have to do the mapping for the container itself, elsewhere. + if !createMappedLayer { return layer, nil } // The top layer's mappings don't match the ones we want, and it's in an image store // that lets us edit image metadata... if istore, ok := ristore.(*imageStore); ok { - // ... so extract the layer's contents, create a new copy of it with the - // desired mappings, and register it as an alternate top layer in the image. - noCompression := archive.Uncompressed - diffOptions := DiffOptions{ - Compression: &noCompression, - } - rc, err := layerHomeStore.Diff("", layer.ID, &diffOptions) - if err != nil { - return nil, errors.Wrapf(err, "error reading layer %q to create an ID-mapped version of it", layer.ID) - } - defer rc.Close() - + // ... so create a duplicate of the layer with the desired mappings, and + // register it as an alternate top layer in the image. var layerOptions LayerOptions if s.graphDriver.SupportsShifting() { - layerOptions = LayerOptions{IDMappingOptions: IDMappingOptions{HostUIDMapping: true, HostGIDMapping: true, UIDMap: nil, GIDMap: nil}} + layerOptions = LayerOptions{ + IDMappingOptions: IDMappingOptions{ + HostUIDMapping: true, + HostGIDMapping: true, + UIDMap: nil, + GIDMap: nil, + }, + } } else { layerOptions = LayerOptions{ IDMappingOptions: IDMappingOptions{ @@ -1068,9 +1068,10 @@ func (s *store) imageTopLayerForMapping(image *Image, ristore ROImageStore, read }, } } - mappedLayer, _, err := rlstore.Put("", parentLayer, nil, layer.MountLabel, nil, &layerOptions, false, nil, rc) + layerOptions.TemplateLayer = layer.ID + mappedLayer, _, err := rlstore.Put("", parentLayer, nil, layer.MountLabel, nil, &layerOptions, false, nil, nil) if err != nil { - return nil, errors.Wrapf(err, "error creating ID-mapped copy of layer %q", layer.ID) + return nil, errors.Wrapf(err, "error creating an ID-mapped copy of layer %q", layer.ID) } if err = istore.addMappedTopLayer(image.ID, mappedLayer.ID); err != nil { if err2 := rlstore.Delete(mappedLayer.ID); err2 != nil { @@ -1144,7 +1145,9 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat } imageID = cimage.ID - ilayer, err := s.imageTopLayerForMapping(cimage, imageHomeStore, imageHomeStore == istore, rlstore, lstores, idMappingsOptions) + createMappedLayer := imageHomeStore == istore + + ilayer, err := s.imageTopLayerForMapping(cimage, imageHomeStore, createMappedLayer, rlstore, lstores, idMappingsOptions) if err != nil { return nil, err } @@ -1170,7 +1173,14 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat } var layerOptions *LayerOptions if s.graphDriver.SupportsShifting() { - layerOptions = &LayerOptions{IDMappingOptions: IDMappingOptions{HostUIDMapping: true, HostGIDMapping: true, UIDMap: nil, GIDMap: nil}} + layerOptions = &LayerOptions{ + IDMappingOptions: IDMappingOptions{ + HostUIDMapping: true, + HostGIDMapping: true, + UIDMap: nil, + GIDMap: nil, + }, + } } else { layerOptions = &LayerOptions{ IDMappingOptions: IDMappingOptions{ @@ -2091,10 +2101,10 @@ func (s *store) DeleteImage(id string, commit bool) (layers []string, err error) break } lastRemoved = layer - layersToRemove = append(layersToRemove, lastRemoved) if layer == image.TopLayer { layersToRemove = append(layersToRemove, image.MappedTopLayers...) } + layersToRemove = append(layersToRemove, lastRemoved) layer = parent } } else { @@ -3064,9 +3074,6 @@ type OptionsConfig struct { // Size Size string `toml:"size"` - // OverrideKernelCheck - OverrideKernelCheck string `toml:"override_kernel_check"` - // RemapUIDs is a list of default UID mappings to use for layers. RemapUIDs string `toml:"remap-uids"` // RemapGIDs is a list of default GID mappings to use for layers. @@ -3191,9 +3198,6 @@ func ReloadConfigurationFile(configFile string, storeOptions *StoreOptions) { if config.Storage.Options.MountOpt != "" { storeOptions.GraphDriverOptions = append(storeOptions.GraphDriverOptions, fmt.Sprintf("%s.mountopt=%s", config.Storage.Driver, config.Storage.Options.MountOpt)) } - if config.Storage.Options.OverrideKernelCheck != "" { - storeOptions.GraphDriverOptions = append(storeOptions.GraphDriverOptions, fmt.Sprintf("%s.override_kernel_check=%s", config.Storage.Driver, config.Storage.Options.OverrideKernelCheck)) - } if config.Storage.Options.RemapUser != "" && config.Storage.Options.RemapGroup == "" { config.Storage.Options.RemapGroup = config.Storage.Options.RemapUser } diff --git a/vendor/github.com/varlink/go/.gitignore b/vendor/github.com/varlink/go/.gitignore index 69e30cff1..a43b0e2d3 100644 --- a/vendor/github.com/varlink/go/.gitignore +++ b/vendor/github.com/varlink/go/.gitignore @@ -1 +1,2 @@ /cmd/varlink-go-certification/orgvarlinkcertification/orgvarlinkcertification.go +/.idea diff --git a/vendor/github.com/varlink/go/.travis.yml b/vendor/github.com/varlink/go/.travis.yml index c090a924f..fa9963500 100644 --- a/vendor/github.com/varlink/go/.travis.yml +++ b/vendor/github.com/varlink/go/.travis.yml @@ -1,11 +1,13 @@ language: go sudo: false go: -- '1.9' -- 1.10.x +- '1.10' +- 1.11.x install: - go get golang.org/x/tools/cmd/cover - go get github.com/mattn/goveralls +- go get github.com/TylerBrock/colorjson +- go get github.com/fatih/color script: - go generate ./... - '"$HOME/gopath/bin/goveralls" -v -show -service=travis-ci -repotoken "$COVERALLS_TOKEN"' diff --git a/vendor/github.com/varlink/go/cmd/varlink/main.go b/vendor/github.com/varlink/go/cmd/varlink/main.go new file mode 100644 index 000000000..1de4e1a45 --- /dev/null +++ b/vendor/github.com/varlink/go/cmd/varlink/main.go @@ -0,0 +1,295 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "github.com/TylerBrock/colorjson" + "github.com/fatih/color" + "github.com/varlink/go/varlink" + "os" + "strings" +) + +var bold = color.New(color.Bold) +var errorBoldRed = bold.Sprint(color.New(color.FgRed).Sprint("Error:")) +var bridge string + +func ErrPrintf(format string, a ...interface{}) { + fmt.Fprintf(os.Stderr, "%s ", errorBoldRed) + fmt.Fprintf(os.Stderr, format, a...) +} + +func print_usage(set *flag.FlagSet, arg_help string) { + if set == nil { + fmt.Fprintf(os.Stderr, "Usage: %s [GLOBAL OPTIONS] COMMAND ...\n", os.Args[0]) + } else { + fmt.Fprintf(os.Stderr, "Usage: %s [GLOBAL OPTIONS] %s [OPTIONS] %s\n", os.Args[0], set.Name(), arg_help) + } + + fmt.Fprintln(os.Stderr, "\nGlobal Options:") + flag.PrintDefaults() + + if set == nil { + fmt.Fprintln(os.Stderr, "\nCommands:") + fmt.Fprintln(os.Stderr, " info\tPrint information about a service") + fmt.Fprintln(os.Stderr, " help\tPrint interface description or service information") + fmt.Fprintln(os.Stderr, " call\tCall a method") + } else { + fmt.Fprintln(os.Stderr, "\nOptions:") + set.PrintDefaults() + } + os.Exit(1) +} + +func varlink_call(args []string) { + var err error + var oneway bool + + callFlags := flag.NewFlagSet("help", flag.ExitOnError) + callFlags.BoolVar(&oneway, "-oneway", false, "Use bridge for connection") + var help bool + callFlags.BoolVar(&help, "help", false, "Prints help information") + var usage = func() { print_usage(callFlags, "<[ADDRESS/]INTERFACE.METHOD> [ARGUMENTS]") } + callFlags.Usage = usage + + _ = callFlags.Parse(args) + + if help { + usage() + } + + var con *varlink.Connection + var address string + var methodName string + + if len(bridge) != 0 { + con, err = varlink.NewBridge(bridge) + + if err != nil { + ErrPrintf("Cannot connect with bridge '%s': %v\n", bridge, err) + os.Exit(2) + } + address = "bridge:" + bridge + methodName = callFlags.Arg(0) + } else { + uri := callFlags.Arg(0) + if uri == "" { + usage() + } + + li := strings.LastIndex(uri, "/") + + if li == -1 { + ErrPrintf("Invalid address '%s'\n", uri) + os.Exit(2) + } + + address = uri[:li] + methodName = uri[li+1:] + + con, err = varlink.NewConnection(address) + + if err != nil { + ErrPrintf("Cannot connect to '%s': %v\n", address, err) + os.Exit(2) + } + } + var parameters string + var params json.RawMessage + + parameters = callFlags.Arg(1) + if parameters == "" { + params = nil + } else { + json.Unmarshal([]byte(parameters), ¶ms) + } + + var flags uint64 + flags = 0 + if oneway { + flags |= varlink.Oneway + } + recv, err := con.Send(methodName, params, flags) + + var retval map[string]interface{} + + // FIXME: Use cont + _, err = recv(&retval) + + f := colorjson.NewFormatter() + f.Indent = 2 + f.KeyColor = color.New(color.FgCyan) + f.StringColor = color.New(color.FgMagenta) + f.NumberColor = color.New(color.FgMagenta) + f.BoolColor = color.New(color.FgMagenta) + f.NullColor = color.New(color.FgMagenta) + + if err != nil { + ErrPrintf("Error calling '%s': %v\n", methodName, err) + switch e := err.(type) { + case *varlink.Error: + println(e.Name) + errorRawParameters := e.Parameters.(*json.RawMessage) + + if errorRawParameters == nil { + break + } + var param map[string]interface{} + _ = json.Unmarshal(*errorRawParameters, ¶m) + c, _ := f.Marshal(param) + ErrPrintf("%v\n", string(c)) + } + os.Exit(2) + } + c, _ := f.Marshal(retval) + fmt.Println(string(c)) +} + +func varlink_help(args []string) { + var err error + + helpFlags := flag.NewFlagSet("help", flag.ExitOnError) + var help bool + helpFlags.BoolVar(&help, "help", false, "Prints help information") + var usage = func() { print_usage(helpFlags, "<[ADDRESS/]INTERFACE>") } + helpFlags.Usage = usage + + _ = helpFlags.Parse(args) + + if help { + usage() + } + + var con *varlink.Connection + var address string + var interfaceName string + + if len(bridge) != 0 { + con, err = varlink.NewBridge(bridge) + + if err != nil { + ErrPrintf("Cannot connect with bridge '%s': %v\n", bridge, err) + os.Exit(2) + } + address = "bridge:" + bridge + interfaceName = helpFlags.Arg(0) + } else { + uri := helpFlags.Arg(0) + if uri == "" && bridge == "" { + ErrPrintf("No ADDRESS or activation or bridge\n\n") + usage() + } + + li := strings.LastIndex(uri, "/") + + if li == -1 { + ErrPrintf("Invalid address '%s'\n", uri) + os.Exit(2) + } + + address = uri[:li] + + con, err = varlink.NewConnection(address) + + if err != nil { + ErrPrintf("Cannot connect to '%s': %v\n", address, err) + os.Exit(2) + } + + interfaceName = uri[li+1:] + } + description, err := con.GetInterfaceDescription(interfaceName) + + if err != nil { + ErrPrintf("Cannot get interface description for '%s': %v\n", interfaceName, err) + os.Exit(2) + } + + fmt.Println(description) +} + +func varlink_info(args []string) { + var err error + infoFlags := flag.NewFlagSet("info", flag.ExitOnError) + var help bool + infoFlags.BoolVar(&help, "help", false, "Prints help information") + var usage = func() { print_usage(infoFlags, "[ADDRESS]") } + infoFlags.Usage = usage + + _ = infoFlags.Parse(args) + + if help { + usage() + } + + var con *varlink.Connection + var address string + + if len(bridge) != 0 { + con, err = varlink.NewBridge(bridge) + + if err != nil { + ErrPrintf("Cannot connect with bridge '%s': %v\n", bridge, err) + os.Exit(2) + } + address = "bridge:" + bridge + } else { + address = infoFlags.Arg(0) + + if address == "" && bridge == "" { + ErrPrintf("No ADDRESS or activation or bridge\n\n") + usage() + } + + con, err = varlink.NewConnection(address) + + if err != nil { + ErrPrintf("Cannot connect to '%s': %v\n", address, err) + os.Exit(2) + } + } + + var vendor, product, version, url string + var interfaces []string + + err = con.GetInfo(&vendor, &product, &version, &url, &interfaces) + + if err != nil { + ErrPrintf("Cannot get info for '%s': %v\n", address, err) + os.Exit(2) + } + + fmt.Printf("%s %s\n", bold.Sprint("Vendor:"), vendor) + fmt.Printf("%s %s\n", bold.Sprint("Product:"), product) + fmt.Printf("%s %s\n", bold.Sprint("Version:"), version) + fmt.Printf("%s %s\n", bold.Sprint("URL:"), url) + fmt.Printf("%s\n %s\n\n", bold.Sprint("Interfaces:"), strings.Join(interfaces[:], "\n ")) +} + +func main() { + var debug bool + var colorMode string + + flag.CommandLine.Usage = func() { print_usage(nil, "") } + flag.BoolVar(&debug, "debug", false, "Enable debug output") + flag.StringVar(&bridge, "bridge", "", "Use bridge for connection") + flag.StringVar(&colorMode, "color", "auto", "colorize output [default: auto] [possible values: on, off, auto]") + + flag.Parse() + + if colorMode != "on" && (os.Getenv("TERM") == "" || colorMode == "off") { + color.NoColor = true // disables colorized output + } + + switch flag.Arg(0) { + case "info": + varlink_info(flag.Args()[1:]) + case "help": + varlink_help(flag.Args()[1:]) + case "call": + varlink_call(flag.Args()[1:]) + default: + print_usage(nil, "") + } +} diff --git a/vendor/github.com/varlink/go/varlink/bridge.go b/vendor/github.com/varlink/go/varlink/bridge.go new file mode 100644 index 000000000..b20c0925a --- /dev/null +++ b/vendor/github.com/varlink/go/varlink/bridge.go @@ -0,0 +1,59 @@ +// +build !windows + +package varlink + +import ( + "bufio" + "io" + "log" + "net" + "os/exec" +) + +type PipeCon struct { + net.Conn + reader *io.ReadCloser + writer *io.WriteCloser +} + +func (p PipeCon) Close() error { + err1 := (*p.reader).Close() + err2 := (*p.writer).Close() + if err1 != nil { + return err1 + } + if err2 != nil { + return err2 + } + return nil +} + +// NewConnection returns a new connection to the given address. +func NewBridge(bridge string) (*Connection, error) { + //var err error + + c := Connection{} + cmd := exec.Command("sh", "-c", bridge) + r, err := cmd.StdoutPipe() + if err != nil { + return nil, err + } + w, err := cmd.StdinPipe() + if err != nil { + return nil, err + } + c.conn = PipeCon{nil, &r, &w} + c.address = "" + c.reader = bufio.NewReader(r) + c.writer = bufio.NewWriter(w) + + go func() { + err := cmd.Run() + if err != nil { + log.Fatal(err) + } + }() + + return &c, nil +} + diff --git a/vendor/github.com/varlink/go/varlink/bridge_windows.go b/vendor/github.com/varlink/go/varlink/bridge_windows.go new file mode 100644 index 000000000..692367a1a --- /dev/null +++ b/vendor/github.com/varlink/go/varlink/bridge_windows.go @@ -0,0 +1,57 @@ +package varlink + +import ( + "bufio" + "io" + "log" + "net" + "os/exec" +) + +type PipeCon struct { + net.Conn + reader *io.ReadCloser + writer *io.WriteCloser +} + +func (p PipeCon) Close() error { + err1 := (*p.reader).Close() + err2 := (*p.writer).Close() + if err1 != nil { + return err1 + } + if err2 != nil { + return err2 + } + return nil +} + +// NewConnection returns a new connection to the given address. +func NewBridge(bridge string) (*Connection, error) { + //var err error + + c := Connection{} + cmd := exec.Command("cmd", "/C", bridge) + r, err := cmd.StdoutPipe() + if err != nil { + return nil, err + } + w, err := cmd.StdinPipe() + if err != nil { + return nil, err + } + c.conn = PipeCon{nil, &r, &w} + c.address = "" + c.reader = bufio.NewReader(r) + c.writer = bufio.NewWriter(w) + + go func() { + err := cmd.Run() + if err != nil { + log.Fatal(err) + } + }() + + return &c, nil +} + diff --git a/vendor/github.com/varlink/go/varlink/connection.go b/vendor/github.com/varlink/go/varlink/connection.go index 43bec6393..ac9542408 100644 --- a/vendor/github.com/varlink/go/varlink/connection.go +++ b/vendor/github.com/varlink/go/varlink/connection.go @@ -3,6 +3,7 @@ package varlink import ( "bufio" "encoding/json" + "fmt" "net" "strings" ) @@ -18,6 +19,7 @@ const ( // Error is a varlink error returned from a method call. type Error struct { + error Name string Parameters interface{} } @@ -189,6 +191,11 @@ func NewConnection(address string) (*Connection, error) { var err error words := strings.SplitN(address, ":", 2) + + if len(words) != 2 { + return nil, fmt.Errorf("Protocol missing") + } + protocol := words[0] addr := words[1] diff --git a/vendor/github.com/varlink/go/varlink/service.go b/vendor/github.com/varlink/go/varlink/service.go index 551ba4e53..cb461f917 100644 --- a/vendor/github.com/varlink/go/varlink/service.go +++ b/vendor/github.com/varlink/go/varlink/service.go @@ -6,10 +6,8 @@ import ( "fmt" "net" "os" - "strconv" "strings" "sync" - "syscall" "time" ) @@ -110,58 +108,6 @@ func (s *Service) handleMessage(writer *bufio.Writer, request []byte) error { return iface.VarlinkDispatch(c, methodname) } -func activationListener() net.Listener { - pid, err := strconv.Atoi(os.Getenv("LISTEN_PID")) - if err != nil || pid != os.Getpid() { - return nil - } - - nfds, err := strconv.Atoi(os.Getenv("LISTEN_FDS")) - if err != nil || nfds < 1 { - return nil - } - - fd := -1 - - // If more than one file descriptor is passed, find the - // "varlink" tag. The first file descriptor is always 3. - if nfds > 1 { - fdnames, set := os.LookupEnv("LISTEN_FDNAMES") - if !set { - return nil - } - - names := strings.Split(fdnames, ":") - if len(names) != nfds { - return nil - } - - for i, name := range names { - if name == "varlink" { - fd = 3 + i - break - } - } - - if fd < 0 { - return nil - } - - } else { - fd = 3 - } - - syscall.CloseOnExec(fd) - - file := os.NewFile(uintptr(fd), "varlink") - listener, err := net.FileListener(file) - if err != nil { - return nil - } - - return listener -} - // Shutdown shuts down the listener of a running service. func (s *Service) Shutdown() { s.running = false @@ -253,18 +199,17 @@ func getListener(protocol string, address string) (net.Listener, error) { } func (s *Service) refreshTimeout(timeout time.Duration) error { - switch s.protocol { - case "unix": - if err := s.listener.(*net.UnixListener).SetDeadline(time.Now().Add(timeout)); err != nil { + switch l := s.listener.(type) { + case *net.UnixListener: + if err:= l.SetDeadline(time.Now().Add(timeout)); err != nil { return err } - - case "tcp": - if err := s.listener.(*net.TCPListener).SetDeadline(time.Now().Add(timeout)); err != nil { + case *net.TCPListener: + if err:= l.SetDeadline(time.Now().Add(timeout)); err != nil { return err } - } + } return nil } diff --git a/vendor/github.com/varlink/go/varlink/socketactivation.go b/vendor/github.com/varlink/go/varlink/socketactivation.go new file mode 100644 index 000000000..a64c0dc8e --- /dev/null +++ b/vendor/github.com/varlink/go/varlink/socketactivation.go @@ -0,0 +1,63 @@ +// +build !windows + +package varlink + +import ( + "net" + "os" + "strconv" + "strings" + "syscall" +) + +func activationListener() net.Listener { + pid, err := strconv.Atoi(os.Getenv("LISTEN_PID")) + if err != nil || pid != os.Getpid() { + return nil + } + + nfds, err := strconv.Atoi(os.Getenv("LISTEN_FDS")) + if err != nil || nfds < 1 { + return nil + } + + fd := -1 + + // If more than one file descriptor is passed, find the + // "varlink" tag. The first file descriptor is always 3. + if nfds > 1 { + fdnames, set := os.LookupEnv("LISTEN_FDNAMES") + if !set { + return nil + } + + names := strings.Split(fdnames, ":") + if len(names) != nfds { + return nil + } + + for i, name := range names { + if name == "varlink" { + fd = 3 + i + break + } + } + + if fd < 0 { + return nil + } + + } else { + fd = 3 + } + + syscall.CloseOnExec(fd) + + file := os.NewFile(uintptr(fd), "varlink") + listener, err := net.FileListener(file) + if err != nil { + return nil + } + + return listener +} diff --git a/vendor/github.com/varlink/go/varlink/socketactivation_windows.go b/vendor/github.com/varlink/go/varlink/socketactivation_windows.go new file mode 100644 index 000000000..fb0894531 --- /dev/null +++ b/vendor/github.com/varlink/go/varlink/socketactivation_windows.go @@ -0,0 +1,7 @@ +package varlink + +import "net" + +func activationListener() net.Listener { + return nil +} |