// TarLayer returns a tar archive of the image's filesystem layer. func (img *Image) TarLayer() (arch archive.Archive, err error) { if img.graph == nil { return nil, fmt.Errorf("Can't load storage driver for unregistered image %s", img.ID) } driver := img.graph.Driver() if differ, ok := driver.(graphdriver.Differ); ok { return differ.Diff(img.ID) } imgFs, err := driver.Get(img.ID, "") if err != nil { return nil, err } defer func() { if err != nil { driver.Put(img.ID) } }() if img.Parent == "" { archive, err := archive.Tar(imgFs, archive.Uncompressed) if err != nil { return nil, err } return utils.NewReadCloserWrapper(archive, func() error { err := archive.Close() driver.Put(img.ID) return err }), nil } parentFs, err := driver.Get(img.Parent, "") if err != nil { return nil, err } defer driver.Put(img.Parent) changes, err := archive.ChangesDirs(imgFs, parentFs) if err != nil { return nil, err } archive, err := archive.ExportChanges(imgFs, changes) if err != nil { return nil, err } return utils.NewReadCloserWrapper(archive, func() error { err := archive.Close() driver.Put(img.ID) return err }), nil }
func (container *Container) Copy(resource string) (io.ReadCloser, error) { if err := container.Mount(); err != nil { return nil, err } var filter []string basePath := path.Join(container.basefs, resource) stat, err := os.Stat(basePath) if err != nil { container.Unmount() return nil, err } if !stat.IsDir() { d, f := path.Split(basePath) basePath = d filter = []string{f} } else { filter = []string{path.Base(basePath)} basePath = path.Dir(basePath) } archive, err := archive.TarFilter(basePath, &archive.TarOptions{ Compression: archive.Uncompressed, Includes: filter, }) if err != nil { return nil, err } return utils.NewReadCloserWrapper(archive, func() error { err := archive.Close() container.Unmount() return err }), nil }
func (runtime *Runtime) Diff(container *Container) (archive.Archive, error) { if differ, ok := runtime.driver.(graphdriver.Differ); ok { return differ.Diff(container.ID) } changes, err := runtime.Changes(container) if err != nil { return nil, err } cDir, err := runtime.driver.Get(container.ID) if err != nil { return nil, fmt.Errorf("Error getting container rootfs %s from driver %s: %s", container.ID, container.runtime.driver, err) } archive, err := archive.ExportChanges(cDir, changes) if err != nil { return nil, err } return utils.NewReadCloserWrapper(archive, func() error { err := archive.Close() runtime.driver.Put(container.ID) return err }), nil }
func (container *Container) Export() (archive.Archive, error) { if err := container.Mount(); err != nil { return nil, err } archive, err := archive.Tar(container.basefs, archive.Uncompressed) if err != nil { container.Unmount() return nil, err } return utils.NewReadCloserWrapper(archive, func() error { err := archive.Close() container.Unmount() return err }), nil }
func (container *Container) ExportRw() (archive.Archive, error) { if err := container.Mount(); err != nil { return nil, err } if container.runtime == nil { return nil, fmt.Errorf("Can't load storage driver for unregistered container %s", container.ID) } archive, err := container.runtime.Diff(container) if err != nil { container.Unmount() return nil, err } return utils.NewReadCloserWrapper(archive, func() error { err := archive.Close() container.Unmount() return err }), nil }
func (cli *DockerCli) call(method, path string, data interface{}, passAuthInfo bool) (io.ReadCloser, int, error) { params := bytes.NewBuffer(nil) if data != nil { if env, ok := data.(engine.Env); ok { if err := env.Encode(params); err != nil { return nil, -1, err } } else { buf, err := json.Marshal(data) if err != nil { return nil, -1, err } if _, err := params.Write(buf); err != nil { return nil, -1, err } } } // fixme: refactor client to support redirect re := regexp.MustCompile("/+") path = re.ReplaceAllString(path, "/") req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), params) if err != nil { return nil, -1, err } if passAuthInfo { cli.LoadConfigFile() // Resolve the Auth config relevant for this server authConfig := cli.configFile.ResolveAuthConfig(registry.IndexServerAddress()) getHeaders := func(authConfig registry.AuthConfig) (map[string][]string, error) { buf, err := json.Marshal(authConfig) if err != nil { return nil, err } registryAuthHeader := []string{ base64.URLEncoding.EncodeToString(buf), } return map[string][]string{"X-Registry-Auth": registryAuthHeader}, nil } if headers, err := getHeaders(authConfig); err == nil && headers != nil { for k, v := range headers { req.Header[k] = v } } } req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION) req.Host = cli.addr if data != nil { req.Header.Set("Content-Type", "application/json") } else if method == "POST" { req.Header.Set("Content-Type", "plain/text") } dial, err := cli.dial() if err != nil { if strings.Contains(err.Error(), "connection refused") { return nil, -1, ErrConnectionRefused } return nil, -1, err } clientconn := httputil.NewClientConn(dial, nil) resp, err := clientconn.Do(req) if err != nil { clientconn.Close() if strings.Contains(err.Error(), "connection refused") { return nil, -1, ErrConnectionRefused } return nil, -1, err } if resp.StatusCode < 200 || resp.StatusCode >= 400 { body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, -1, err } if len(body) == 0 { return nil, resp.StatusCode, fmt.Errorf("Error: request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(resp.StatusCode), req.URL) } return nil, resp.StatusCode, fmt.Errorf("Error: %s", bytes.TrimSpace(body)) } wrapper := utils.NewReadCloserWrapper(resp.Body, func() error { if resp != nil && resp.Body != nil { resp.Body.Close() } return clientconn.Close() }) return wrapper, resp.StatusCode, nil }