import.go 3.5 KB

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