func TestByParent(t *testing.T) { archive1, _ := fakeTar() archive2, _ := fakeTar() archive3, _ := fakeTar() graph, _ := tempGraph(t) defer nukeGraph(graph) parentImage := &image.Image{ ID: stringid.GenerateNonCryptoID(), Comment: "parent", Created: time.Now(), Parent: "", } childImage1 := &image.Image{ ID: stringid.GenerateNonCryptoID(), Comment: "child1", Created: time.Now(), Parent: parentImage.ID, } childImage2 := &image.Image{ ID: stringid.GenerateNonCryptoID(), Comment: "child2", Created: time.Now(), Parent: parentImage.ID, } _ = graph.Register(parentImage, archive1) _ = graph.Register(childImage1, archive2) _ = graph.Register(childImage2, archive3) byParent := graph.ByParent() numChildren := len(byParent[parentImage.ID]) if numChildren != 2 { t.Fatalf("Expected 2 children, found %d", numChildren) } }
// requestIDMiddleware generates a uniq ID for each request. // This ID travels inside the context for tracing purposes. func requestIDMiddleware(handler HTTPAPIFunc) HTTPAPIFunc { return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { reqID := stringid.TruncateID(stringid.GenerateNonCryptoID()) ctx = context.WithValue(ctx, context.RequestID, reqID) return handler(ctx, w, r, vars) } }
// ContainerExecCreate sets up an exec in a running container. func (d *Daemon) ContainerExecCreate(config *runconfig.ExecConfig) (string, error) { container, err := d.getActiveContainer(config.Container) if err != nil { return "", err } cmd := stringutils.NewStrSlice(config.Cmd...) entrypoint, args := d.getEntrypointAndArgs(stringutils.NewStrSlice(), cmd) processConfig := &execdriver.ProcessConfig{ CommonProcessConfig: execdriver.CommonProcessConfig{ Tty: config.Tty, Entrypoint: entrypoint, Arguments: args, }, } setPlatformSpecificExecProcessConfig(config, container, processConfig) ExecConfig := &ExecConfig{ ID: stringid.GenerateNonCryptoID(), OpenStdin: config.AttachStdin, OpenStdout: config.AttachStdout, OpenStderr: config.AttachStderr, streamConfig: streamConfig{}, ProcessConfig: processConfig, Container: container, Running: false, waitStart: make(chan struct{}), } d.registerExecCommand(ExecConfig) return ExecConfig.ID, nil }
// NewConfig initializes the a new exec configuration func NewConfig() *Config { return &Config{ ID: stringid.GenerateNonCryptoID(), StreamConfig: runconfig.NewStreamConfig(), waitStart: make(chan struct{}), } }
// CreateFromContext creates a plugin from the given pluginDir which contains // both the rootfs and the config.json and a repoName with optional tag. func (pm *Manager) CreateFromContext(ctx context.Context, tarCtx io.Reader, options *types.PluginCreateOptions) error { repoName := options.RepoName ref, err := distribution.GetRef(repoName) if err != nil { return err } name := ref.Name() tag := distribution.GetTag(ref) pluginID := stringid.GenerateNonCryptoID() p := v2.NewPlugin(name, pluginID, pm.runRoot, pm.libRoot, tag) if v, _ := pm.pluginStore.GetByName(p.Name()); v != nil { return fmt.Errorf("plugin %q already exists", p.Name()) } pluginDir := filepath.Join(pm.libRoot, pluginID) if err := os.MkdirAll(pluginDir, 0755); err != nil { return err } // In case an error happens, remove the created directory. if err := pm.createFromContext(ctx, tarCtx, pluginDir, repoName, p); err != nil { if err := os.RemoveAll(pluginDir); err != nil { logrus.Warnf("unable to remove %q from failed plugin creation: %v", pluginDir, err) } return err } return nil }
func TestRegister(t *testing.T) { graph, _ := tempGraph(t) defer nukeGraph(graph) archive, err := fakeTar() if err != nil { t.Fatal(err) } image := &image.Image{ ID: stringid.GenerateNonCryptoID(), Comment: "testing", Created: time.Now(), } err = graph.Register(image, archive) if err != nil { t.Fatal(err) } images := graph.Map() if l := len(images); l != 1 { t.Fatalf("Wrong number of images. Should be %d, not %d", 1, l) } if resultImg, err := graph.Get(image.ID); err != nil { t.Fatal(err) } else { if resultImg.ID != image.ID { t.Fatalf("Wrong image ID. Should be '%s', not '%s'", image.ID, resultImg.ID) } if resultImg.Comment != image.Comment { t.Fatalf("Wrong image comment. Should be '%s', not '%s'", image.Comment, resultImg.Comment) } } }
// mktemp creates a temporary sub-directory inside the graph's filesystem. func (graph *Graph) mktemp(id string) (string, error) { dir := filepath.Join(graph.root, "_tmp", stringid.GenerateNonCryptoID()) if err := system.MkdirAll(dir, 0700); err != nil { return "", err } return dir, nil }
// CreateFromContext creates a plugin from the given pluginDir which contains // both the rootfs and the config.json and a repoName with optional tag. func (pm *Manager) CreateFromContext(ctx context.Context, tarCtx io.Reader, options *types.PluginCreateOptions) error { pluginID := stringid.GenerateNonCryptoID() pluginDir := filepath.Join(pm.libRoot, pluginID) if err := os.MkdirAll(pluginDir, 0755); err != nil { return err } if err := chrootarchive.Untar(tarCtx, pluginDir, nil); err != nil { return err } repoName := options.RepoName ref, err := distribution.GetRef(repoName) if err != nil { return err } name := ref.Name() tag := distribution.GetTag(ref) p := v2.NewPlugin(name, pluginID, pm.runRoot, pm.libRoot, tag) if err := p.InitPlugin(); err != nil { return err } pm.pluginStore.Add(p) pm.pluginEventLogger(p.GetID(), repoName, "create") return nil }
// Pull pulls a plugin and computes the privileges required to install it. func (pm *Manager) Pull(name string, metaHeader http.Header, authConfig *types.AuthConfig) (types.PluginPrivileges, error) { ref, err := distribution.GetRef(name) if err != nil { logrus.Debugf("error in distribution.GetRef: %v", err) return nil, err } name = ref.String() if p, _ := pm.pluginStore.GetByName(name); p != nil { logrus.Debug("plugin already exists") return nil, fmt.Errorf("%s exists", name) } pluginID := stringid.GenerateNonCryptoID() pluginDir := filepath.Join(pm.libRoot, pluginID) if err := os.MkdirAll(pluginDir, 0755); err != nil { logrus.Debugf("error in MkdirAll: %v", err) return nil, err } priv, err := pm.pull(ref, metaHeader, authConfig, pluginID) if err != nil { if err := os.RemoveAll(pluginDir); err != nil { logrus.Warnf("unable to remove %q from failed plugin pull: %v", pluginDir, err) } return nil, err } return priv, nil }
// Setup sets up a mount point by either mounting the volume if it is // configured, or creating the source directory if supplied. func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int) (string, error) { if m.Volume != nil { if m.ID == "" { m.ID = stringid.GenerateNonCryptoID() } path, err := m.Volume.Mount(m.ID) return path, errors.Wrapf(err, "error while mounting volume '%s'", m.Source) } if len(m.Source) == 0 { return "", fmt.Errorf("Unable to setup mount point, neither source nor volume defined") } // system.MkdirAll() produces an error if m.Source exists and is a file (not a directory), if m.Type == mounttypes.TypeBind { // idtools.MkdirAllNewAs() produces an error if m.Source exists and is a file (not a directory) // also, makes sure that if the directory is created, the correct remapped rootUID/rootGID will own it if err := idtools.MkdirAllNewAs(m.Source, 0755, rootUID, rootGID); err != nil { if perr, ok := err.(*os.PathError); ok { if perr.Err != syscall.ENOTDIR { return "", errors.Wrapf(err, "error while creating mount source path '%s'", m.Source) } } } } if label.RelabelNeeded(m.Mode) { if err := label.Relabel(m.Source, mountLabel, label.IsShared(m.Mode)); err != nil { return "", errors.Wrapf(err, "error setting label on mount source '%s'", m.Source) } } return m.Source, nil }
// NewBuilder creates a new Dockerfile builder from an optional dockerfile and a Config. // If dockerfile is nil, the Dockerfile specified by Config.DockerfileName, // will be read from the Context passed to Build(). func NewBuilder(clientCtx context.Context, config *types.ImageBuildOptions, backend builder.Backend, buildContext builder.Context, dockerfile io.ReadCloser) (b *Builder, err error) { if config == nil { config = new(types.ImageBuildOptions) } if config.BuildArgs == nil { config.BuildArgs = make(map[string]string) } ctx, cancel := context.WithCancel(clientCtx) b = &Builder{ clientCtx: ctx, cancel: cancel, options: config, Stdout: os.Stdout, Stderr: os.Stderr, docker: backend, context: buildContext, runConfig: new(container.Config), tmpContainers: map[string]struct{}{}, id: stringid.GenerateNonCryptoID(), allowedBuildArgs: make(map[string]bool), } if dockerfile != nil { b.dockerfile, err = parser.Parse(dockerfile) if err != nil { return nil, err } } return b, nil }
// CopyImagePathContent copies files in destination to the volume. func (container *Container) CopyImagePathContent(v volume.Volume, destination string) error { rootfs, err := symlink.FollowSymlinkInScope(filepath.Join(container.BaseFS, destination), container.BaseFS) if err != nil { return err } if _, err = ioutil.ReadDir(rootfs); err != nil { if os.IsNotExist(err) { return nil } return err } id := stringid.GenerateNonCryptoID() path, err := v.Mount(id) if err != nil { return err } defer func() { if err := v.Unmount(id); err != nil { logrus.Warnf("error while unmounting volume %s: %v", v.Name(), err) } }() return copyExistingContents(rootfs, path) }
// Setup sets up a mount point by either mounting the volume if it is // configured, or creating the source directory if supplied. func (m *MountPoint) Setup(mountLabel string) (string, error) { if m.Volume != nil { if m.ID == "" { m.ID = stringid.GenerateNonCryptoID() } return m.Volume.Mount(m.ID) } if len(m.Source) == 0 { return "", fmt.Errorf("Unable to setup mount point, neither source nor volume defined") } // system.MkdirAll() produces an error if m.Source exists and is a file (not a directory), if err := system.MkdirAll(m.Source, 0755); err != nil { if perr, ok := err.(*os.PathError); ok { if perr.Err != syscall.ENOTDIR { return "", err } } } if label.RelabelNeeded(m.Mode) { if err := label.Relabel(m.Source, mountLabel, label.IsShared(m.Mode)); err != nil { return "", err } } return m.Source, nil }
// NewBuilder creates a new Dockerfile builder from an optional dockerfile and a Config. // If dockerfile is nil, the Dockerfile specified by Config.DockerfileName, // will be read from the Context passed to Build(). func NewBuilder(config *Config, docker builder.Backend, context builder.Context, dockerfile io.ReadCloser) (b *Builder, err error) { if config == nil { config = new(Config) } if config.BuildArgs == nil { config.BuildArgs = make(map[string]string) } b = &Builder{ Config: config, Stdout: os.Stdout, Stderr: os.Stderr, docker: docker, context: context, runConfig: new(container.Config), tmpContainers: map[string]struct{}{}, cancelled: make(chan struct{}), id: stringid.GenerateNonCryptoID(), allowedBuildArgs: make(map[string]bool), } if dockerfile != nil { b.dockerfile, err = parser.Parse(dockerfile) if err != nil { return nil, err } } return b, nil }
// createContainerPlatformSpecificSettings performs platform specific container create functionality func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, img *image.Image) error { for spec := range config.Volumes { var ( name, destination string parts = strings.Split(spec, ":") ) switch len(parts) { case 2: name, destination = parts[0], filepath.Clean(parts[1]) default: name = stringid.GenerateNonCryptoID() destination = filepath.Clean(parts[0]) } // Skip volumes for which we already have something mounted on that // destination because of a --volume-from. if container.isDestinationMounted(destination) { continue } path, err := container.GetResourcePath(destination) if err != nil { return err } stat, err := os.Stat(path) if err == nil && !stat.IsDir() { return fmt.Errorf("cannot mount volume over existing file, file exists %s", path) } volumeDriver := config.VolumeDriver if destination != "" && img != nil { if _, ok := img.ContainerConfig.Volumes[destination]; ok { // check for whether bind is not specified and then set to local if _, ok := container.MountPoints[destination]; !ok { volumeDriver = volume.DefaultDriverName } } } v, err := container.daemon.createVolume(name, volumeDriver, nil) if err != nil { return err } if err := label.Relabel(v.Path(), container.MountLabel, "z"); err != nil { return err } // never attempt to copy existing content in a container FS to a shared volume if v.DriverName() == volume.DefaultDriverName { if err := container.copyImagePathContent(v, destination); err != nil { return err } } container.addMountPointWithVolume(destination, v, true) } return nil }
func BenchmarkTruncIndexNew500(b *testing.B) { var testSet []string for i := 0; i < 500; i++ { testSet = append(testSet, stringid.GenerateNonCryptoID()) } b.ResetTimer() for i := 0; i < b.N; i++ { NewTruncIndex(testSet) } }
func (s *DockerSuite) TestRenameRunningContainer(c *check.C) { out, _ := dockerCmd(c, "run", "--name", "first_name", "-d", "busybox", "sh") newName := "new_name" + stringid.GenerateNonCryptoID() cleanedContainerID := strings.TrimSpace(out) dockerCmd(c, "rename", "first_name", newName) name := inspectField(c, cleanedContainerID, "Name") c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name)) }
// createContainerPlatformSpecificSettings performs platform specific container create functionality func (daemon *Daemon) createContainerPlatformSpecificSettings(container *container.Container, config *runconfig.Config, hostConfig *runconfig.HostConfig, img *image.Image) error { if err := daemon.Mount(container); err != nil { return err } defer daemon.Unmount(container) for spec := range config.Volumes { name := stringid.GenerateNonCryptoID() destination := filepath.Clean(spec) // Skip volumes for which we already have something mounted on that // destination because of a --volume-from. if container.IsDestinationMounted(destination) { continue } path, err := container.GetResourcePath(destination) if err != nil { return err } stat, err := os.Stat(path) if err == nil && !stat.IsDir() { return derr.ErrorCodeMountOverFile.WithArgs(path) } volumeDriver := hostConfig.VolumeDriver if destination != "" && img != nil { if _, ok := img.ContainerConfig.Volumes[destination]; ok { // check for whether bind is not specified and then set to local if _, ok := container.MountPoints[destination]; !ok { volumeDriver = volume.DefaultDriverName } } } v, err := daemon.createVolume(name, volumeDriver, nil) if err != nil { return err } if err := label.Relabel(v.Path(), container.MountLabel, true); err != nil { return err } // never attempt to copy existing content in a container FS to a shared volume if v.DriverName() == volume.DefaultDriverName { if err := container.CopyImagePathContent(v, destination); err != nil { return err } } container.AddMountPointWithVolume(destination, v, true) } return nil }
// mktemp creates a temporary sub-directory inside the graph's filesystem. func (graph *Graph) mktemp() (string, error) { dir := filepath.Join(graph.root, "_tmp", stringid.GenerateNonCryptoID()) rootUID, rootGID, err := idtools.GetRootUIDGID(graph.uidMaps, graph.gidMaps) if err != nil { return "", err } if err := idtools.MkdirAllAs(dir, 0700, rootUID, rootGID); err != nil { return "", err } return dir, nil }
// VolumeCreate creates a volume with the specified name, driver, and opts // This is called directly from the remote API func (daemon *Daemon) VolumeCreate(name, driverName string, opts map[string]string) (*types.Volume, error) { if name == "" { name = stringid.GenerateNonCryptoID() } v, err := daemon.volumes.Create(name, driverName, opts) if err != nil { return nil, err } return volumeToAPIType(v), nil }
func (s *DockerSuite) TestRenameCheckNames(c *check.C) { dockerCmd(c, "run", "--name", "first_name", "-d", "busybox", "sh") newName := "new_name" + stringid.GenerateNonCryptoID() dockerCmd(c, "rename", "first_name", newName) name := inspectField(c, newName, "Name") c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name)) name, err := inspectFieldWithError("first_name", "Name") c.Assert(err, checker.NotNil, check.Commentf(name)) c.Assert(err.Error(), checker.Contains, "No such image, container or task: first_name") }
func BenchmarkTruncIndexAdd500(b *testing.B) { var testSet []string for i := 0; i < 500; i++ { testSet = append(testSet, stringid.GenerateNonCryptoID()) } b.ResetTimer() for i := 0; i < b.N; i++ { index := NewTruncIndex([]string{}) for _, id := range testSet { if err := index.Add(id); err != nil { b.Fatal(err) } } } }
func (s *DockerSuite) TestRenameCheckNames(c *check.C) { dockerCmd(c, "run", "--name", "first_name", "-d", "busybox", "sh") newName := "new_name" + stringid.GenerateNonCryptoID() dockerCmd(c, "rename", "first_name", newName) name := inspectField(c, newName, "Name") c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name)) result := dockerCmdWithResult("inspect", "-f={{.Name}}", "--type=container", "first_name") c.Assert(result, icmd.Matches, icmd.Expected{ ExitCode: 1, Err: "No such container: first_name", }) }
func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverOutOfBandDelete(c *check.C) { driverName := stringid.GenerateNonCryptoID() p := newVolumePlugin(c, driverName) defer p.Close() s.d.StartWithBusybox(c) out, err := s.d.Cmd("volume", "create", "-d", driverName, "--name", "test") c.Assert(err, checker.IsNil, check.Commentf(out)) out, err = s.d.Cmd("volume", "create", "-d", "local", "--name", "test") c.Assert(err, checker.NotNil, check.Commentf(out)) c.Assert(out, checker.Contains, "volume named test already exists") // simulate out of band volume deletion on plugin level delete(p.vols, "test") // test re-create with same driver out, err = s.d.Cmd("volume", "create", "-d", driverName, "--opt", "foo=bar", "--name", "test") c.Assert(err, checker.IsNil, check.Commentf(out)) out, err = s.d.Cmd("volume", "inspect", "test") c.Assert(err, checker.IsNil, check.Commentf(out)) var vs []types.Volume err = json.Unmarshal([]byte(out), &vs) c.Assert(err, checker.IsNil) c.Assert(vs, checker.HasLen, 1) c.Assert(vs[0].Driver, checker.Equals, driverName) c.Assert(vs[0].Options, checker.NotNil) c.Assert(vs[0].Options["foo"], checker.Equals, "bar") c.Assert(vs[0].Driver, checker.Equals, driverName) // simulate out of band volume deletion on plugin level delete(p.vols, "test") // test create with different driver out, err = s.d.Cmd("volume", "create", "-d", "local", "--name", "test") c.Assert(err, checker.IsNil, check.Commentf(out)) out, err = s.d.Cmd("volume", "inspect", "test") c.Assert(err, checker.IsNil, check.Commentf(out)) vs = nil err = json.Unmarshal([]byte(out), &vs) c.Assert(err, checker.IsNil) c.Assert(vs, checker.HasLen, 1) c.Assert(vs[0].Options, checker.HasLen, 0) c.Assert(vs[0].Driver, checker.Equals, "local") }
// Pull pulls a plugin, check if the correct privileges are provided and install the plugin. func (pm *Manager) Pull(name string, metaHeader http.Header, authConfig *types.AuthConfig, privileges types.PluginPrivileges) (err error) { ref, pd, err := pm.pull(name, metaHeader, authConfig) if err != nil { return err } requiredPrivileges, err := computePrivileges(pd) if err != nil { return err } if !reflect.DeepEqual(privileges, requiredPrivileges) { return errors.New("incorrect privileges") } pluginID := stringid.GenerateNonCryptoID() pluginDir := filepath.Join(pm.libRoot, pluginID) if err := os.MkdirAll(pluginDir, 0755); err != nil { logrus.Debugf("error in MkdirAll: %v", err) return err } defer func() { if err != nil { if delErr := os.RemoveAll(pluginDir); delErr != nil { logrus.Warnf("unable to remove %q from failed plugin pull: %v", pluginDir, delErr) } } }() err = distribution.WritePullData(pd, filepath.Join(pm.libRoot, pluginID), true) if err != nil { logrus.Debugf("error in distribution.WritePullData(): %v", err) return err } tag := distribution.GetTag(ref) p := v2.NewPlugin(ref.Name(), pluginID, pm.runRoot, pm.libRoot, tag) err = p.InitPlugin() if err != nil { return err } pm.pluginStore.Add(p) pm.pluginEventLogger(pluginID, ref.String(), "pull") return nil }
// VolumeCreate creates a volume with the specified name, driver, and opts // This is called directly from the remote API func (daemon *Daemon) VolumeCreate(name, driverName string, opts map[string]string) (*types.Volume, error) { if name == "" { name = stringid.GenerateNonCryptoID() } v, err := daemon.volumes.Create(name, driverName, opts) if err != nil { if volumestore.IsNameConflict(err) { return nil, fmt.Errorf("A volume named %s already exists. Choose a different volume name.", name) } return nil, err } daemon.LogVolumeEvent(v.Name(), "create", map[string]string{"driver": v.DriverName()}) return volumeToAPIType(v), nil }
func (s *DockerSuite) TestRenameStoppedContainer(c *check.C) { testRequires(c, DaemonIsLinux) out, _ := dockerCmd(c, "run", "--name", "first_name", "-d", "busybox", "sh") cleanedContainerID := strings.TrimSpace(out) dockerCmd(c, "wait", cleanedContainerID) name, err := inspectField(cleanedContainerID, "Name") newName := "new_name" + stringid.GenerateNonCryptoID() dockerCmd(c, "rename", "first_name", newName) name, err = inspectField(cleanedContainerID, "Name") c.Assert(err, checker.IsNil, check.Commentf("Failed to rename container %s", name)) c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name)) }
// VolumeCreate creates a volume with the specified name, driver, and opts // This is called directly from the remote API func (daemon *Daemon) VolumeCreate(name, driverName string, opts map[string]string) (*types.Volume, error) { if name == "" { name = stringid.GenerateNonCryptoID() } v, err := daemon.volumes.Create(name, driverName, opts) if err != nil { if volumestore.IsNameConflict(err) { return nil, derr.ErrorVolumeNameTaken.WithArgs(name) } return nil, err } daemon.LogVolumeEvent(v.Name(), "create", map[string]string{"driver": v.DriverName()}) return volumeToAPIType(v), nil }
// VolumeCreate creates a volume with the specified name, driver, and opts // This is called directly from the remote API func (daemon *Daemon) VolumeCreate(name, driverName string, opts map[string]string) (*types.Volume, error) { if name == "" { name = stringid.GenerateNonCryptoID() } v, err := daemon.volumes.Create(name, driverName, opts) if err != nil { return nil, err } // keep "docker run -v existing_volume:/foo --volume-driver other_driver" work if (driverName != "" && v.DriverName() != driverName) || (driverName == "" && v.DriverName() != volume.DefaultDriverName) { return nil, derr.ErrorVolumeNameTaken.WithArgs(name, v.DriverName()) } return volumeToAPIType(v), nil }
func (s *DockerSuite) TestRenameRunningContainer(c *check.C) { testRequires(c, DaemonIsLinux) out, _ := dockerCmd(c, "run", "--name", "first_name", "-d", "busybox", "sh") newName := "new_name" + stringid.GenerateNonCryptoID() cleanedContainerID := strings.TrimSpace(out) dockerCmd(c, "rename", "first_name", newName) name, err := inspectField(cleanedContainerID, "Name") if err != nil { c.Fatal(err) } if name != "/"+newName { c.Fatal("Failed to rename container ") } }