import.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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/builder/remotecontext"
  14. "github.com/docker/docker/dockerversion"
  15. "github.com/docker/docker/image"
  16. "github.com/docker/docker/layer"
  17. "github.com/docker/docker/pkg/archive"
  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, platform string, 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. // Default the platform if not supplied.
  33. if platform == "" {
  34. platform = runtime.GOOS
  35. }
  36. if repository != "" {
  37. var err error
  38. newRef, err = reference.ParseNormalizedNamed(repository)
  39. if err != nil {
  40. return validationError{err}
  41. }
  42. if _, isCanonical := newRef.(reference.Canonical); isCanonical {
  43. return validationError{errors.New("cannot import digest reference")}
  44. }
  45. if tag != "" {
  46. newRef, err = reference.WithTag(newRef, tag)
  47. if err != nil {
  48. return validationError{err}
  49. }
  50. }
  51. }
  52. config, err := dockerfile.BuildFromConfig(&container.Config{}, changes)
  53. if err != nil {
  54. return err
  55. }
  56. if src == "-" {
  57. rc = inConfig
  58. } else {
  59. inConfig.Close()
  60. if len(strings.Split(src, "://")) == 1 {
  61. src = "http://" + src
  62. }
  63. u, err := url.Parse(src)
  64. if err != nil {
  65. return validationError{err}
  66. }
  67. resp, err = remotecontext.GetWithStatusError(u.String())
  68. if err != nil {
  69. return err
  70. }
  71. outStream.Write(streamformatter.FormatStatus("", "Downloading from %s", u))
  72. progressOutput := streamformatter.NewJSONProgressOutput(outStream, true)
  73. rc = progress.NewProgressReader(resp.Body, progressOutput, resp.ContentLength, "", "Importing")
  74. }
  75. defer rc.Close()
  76. if len(msg) == 0 {
  77. msg = "Imported from " + src
  78. }
  79. inflatedLayerData, err := archive.DecompressStream(rc)
  80. if err != nil {
  81. return err
  82. }
  83. l, err := daemon.stores[platform].layerStore.Register(inflatedLayerData, "", layer.Platform(platform))
  84. if err != nil {
  85. return err
  86. }
  87. defer layer.ReleaseAndLog(daemon.stores[platform].layerStore, l)
  88. created := time.Now().UTC()
  89. imgConfig, err := json.Marshal(&image.Image{
  90. V1Image: image.V1Image{
  91. DockerVersion: dockerversion.Version,
  92. Config: config,
  93. Architecture: runtime.GOARCH,
  94. OS: platform,
  95. Created: created,
  96. Comment: msg,
  97. },
  98. RootFS: &image.RootFS{
  99. Type: "layers",
  100. DiffIDs: []layer.DiffID{l.DiffID()},
  101. },
  102. History: []image.History{{
  103. Created: created,
  104. Comment: msg,
  105. }},
  106. })
  107. if err != nil {
  108. return err
  109. }
  110. id, err := daemon.stores[platform].imageStore.Create(imgConfig)
  111. if err != nil {
  112. return err
  113. }
  114. // FIXME: connect with commit code and call refstore directly
  115. if newRef != nil {
  116. if err := daemon.TagImageWithReference(id, platform, newRef); err != nil {
  117. return err
  118. }
  119. }
  120. daemon.LogImageEvent(id.String(), id.String(), "import")
  121. outStream.Write(streamformatter.FormatStatus("", id.String()))
  122. return nil
  123. }