import.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package daemon
  2. import (
  3. "encoding/json"
  4. "io"
  5. "net/http"
  6. "net/url"
  7. "runtime"
  8. "strings"
  9. "time"
  10. "github.com/docker/distribution/reference"
  11. "github.com/docker/docker/api/types/container"
  12. "github.com/docker/docker/builder/dockerfile"
  13. "github.com/docker/docker/dockerversion"
  14. "github.com/docker/docker/image"
  15. "github.com/docker/docker/layer"
  16. "github.com/docker/docker/pkg/archive"
  17. "github.com/docker/docker/pkg/httputils"
  18. "github.com/docker/docker/pkg/progress"
  19. "github.com/docker/docker/pkg/streamformatter"
  20. "github.com/pkg/errors"
  21. )
  22. // ImportImage imports an image, getting the archived layer data either from
  23. // inConfig (if src is "-"), or from a URI specified in src. Progress output is
  24. // written to outStream. Repository and tag names can optionally be given in
  25. // the repo and tag arguments, respectively.
  26. func (daemon *Daemon) ImportImage(src string, repository, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
  27. var (
  28. rc io.ReadCloser
  29. resp *http.Response
  30. newRef reference.Named
  31. )
  32. if repository != "" {
  33. var err error
  34. newRef, err = reference.ParseNormalizedNamed(repository)
  35. if err != nil {
  36. return err
  37. }
  38. if _, isCanonical := newRef.(reference.Canonical); isCanonical {
  39. return errors.New("cannot import digest reference")
  40. }
  41. if tag != "" {
  42. newRef, err = reference.WithTag(newRef, tag)
  43. if err != nil {
  44. return err
  45. }
  46. }
  47. }
  48. config, err := dockerfile.BuildFromConfig(&container.Config{}, changes)
  49. if err != nil {
  50. return err
  51. }
  52. if src == "-" {
  53. rc = inConfig
  54. } else {
  55. inConfig.Close()
  56. if len(strings.Split(src, "://")) == 1 {
  57. src = "http://" + src
  58. }
  59. u, err := url.Parse(src)
  60. if err != nil {
  61. return err
  62. }
  63. resp, err = httputils.Download(u.String())
  64. if err != nil {
  65. return err
  66. }
  67. outStream.Write(streamformatter.FormatStatus("", "Downloading from %s", u))
  68. progressOutput := streamformatter.NewJSONProgressOutput(outStream, true)
  69. rc = progress.NewProgressReader(resp.Body, progressOutput, resp.ContentLength, "", "Importing")
  70. }
  71. defer rc.Close()
  72. if len(msg) == 0 {
  73. msg = "Imported from " + src
  74. }
  75. inflatedLayerData, err := archive.DecompressStream(rc)
  76. if err != nil {
  77. return err
  78. }
  79. // TODO: support windows baselayer?
  80. l, err := daemon.layerStore.Register(inflatedLayerData, "")
  81. if err != nil {
  82. return err
  83. }
  84. defer layer.ReleaseAndLog(daemon.layerStore, l)
  85. created := time.Now().UTC()
  86. imgConfig, err := json.Marshal(&image.Image{
  87. V1Image: image.V1Image{
  88. DockerVersion: dockerversion.Version,
  89. Config: config,
  90. Architecture: runtime.GOARCH,
  91. OS: runtime.GOOS,
  92. Created: created,
  93. Comment: msg,
  94. },
  95. RootFS: &image.RootFS{
  96. Type: "layers",
  97. DiffIDs: []layer.DiffID{l.DiffID()},
  98. },
  99. History: []image.History{{
  100. Created: created,
  101. Comment: msg,
  102. }},
  103. })
  104. if err != nil {
  105. return err
  106. }
  107. id, err := daemon.imageStore.Create(imgConfig)
  108. if err != nil {
  109. return err
  110. }
  111. // FIXME: connect with commit code and call refstore directly
  112. if newRef != nil {
  113. if err := daemon.TagImageWithReference(id, newRef); err != nil {
  114. return err
  115. }
  116. }
  117. daemon.LogImageEvent(id.String(), id.String(), "import")
  118. outStream.Write(streamformatter.FormatStatus("", id.String()))
  119. return nil
  120. }