import.go 3.2 KB

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