store.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. package image
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "sync"
  7. "github.com/Sirupsen/logrus"
  8. "github.com/docker/distribution/digestset"
  9. "github.com/docker/docker/layer"
  10. "github.com/opencontainers/go-digest"
  11. )
  12. // Store is an interface for creating and accessing images
  13. type Store interface {
  14. Create(config []byte) (ID, error)
  15. Get(id ID) (*Image, error)
  16. Delete(id ID) ([]layer.Metadata, error)
  17. Search(partialID string) (ID, error)
  18. SetParent(id ID, parent ID) error
  19. GetParent(id ID) (ID, error)
  20. Children(id ID) []ID
  21. Map() map[ID]*Image
  22. Heads() map[ID]*Image
  23. }
  24. // LayerGetReleaser is a minimal interface for getting and releasing images.
  25. type LayerGetReleaser interface {
  26. Get(layer.ChainID) (layer.Layer, error)
  27. Release(layer.Layer) ([]layer.Metadata, error)
  28. }
  29. type imageMeta struct {
  30. layer layer.Layer
  31. children map[ID]struct{}
  32. }
  33. type store struct {
  34. sync.Mutex
  35. ls LayerGetReleaser
  36. images map[ID]*imageMeta
  37. fs StoreBackend
  38. digestSet *digestset.Set
  39. }
  40. // NewImageStore returns new store object for given layer store
  41. func NewImageStore(fs StoreBackend, ls LayerGetReleaser) (Store, error) {
  42. is := &store{
  43. ls: ls,
  44. images: make(map[ID]*imageMeta),
  45. fs: fs,
  46. digestSet: digestset.NewSet(),
  47. }
  48. // load all current images and retain layers
  49. if err := is.restore(); err != nil {
  50. return nil, err
  51. }
  52. return is, nil
  53. }
  54. func (is *store) restore() error {
  55. err := is.fs.Walk(func(dgst digest.Digest) error {
  56. img, err := is.Get(IDFromDigest(dgst))
  57. if err != nil {
  58. logrus.Errorf("invalid image %v, %v", dgst, err)
  59. return nil
  60. }
  61. var l layer.Layer
  62. if chainID := img.RootFS.ChainID(); chainID != "" {
  63. l, err = is.ls.Get(chainID)
  64. if err != nil {
  65. return err
  66. }
  67. }
  68. if err := is.digestSet.Add(dgst); err != nil {
  69. return err
  70. }
  71. imageMeta := &imageMeta{
  72. layer: l,
  73. children: make(map[ID]struct{}),
  74. }
  75. is.images[IDFromDigest(dgst)] = imageMeta
  76. return nil
  77. })
  78. if err != nil {
  79. return err
  80. }
  81. // Second pass to fill in children maps
  82. for id := range is.images {
  83. if parent, err := is.GetParent(id); err == nil {
  84. if parentMeta := is.images[parent]; parentMeta != nil {
  85. parentMeta.children[id] = struct{}{}
  86. }
  87. }
  88. }
  89. return nil
  90. }
  91. func (is *store) Create(config []byte) (ID, error) {
  92. var img Image
  93. err := json.Unmarshal(config, &img)
  94. if err != nil {
  95. return "", err
  96. }
  97. // Must reject any config that references diffIDs from the history
  98. // which aren't among the rootfs layers.
  99. rootFSLayers := make(map[layer.DiffID]struct{})
  100. for _, diffID := range img.RootFS.DiffIDs {
  101. rootFSLayers[diffID] = struct{}{}
  102. }
  103. layerCounter := 0
  104. for _, h := range img.History {
  105. if !h.EmptyLayer {
  106. layerCounter++
  107. }
  108. }
  109. if layerCounter > len(img.RootFS.DiffIDs) {
  110. return "", errors.New("too many non-empty layers in History section")
  111. }
  112. dgst, err := is.fs.Set(config)
  113. if err != nil {
  114. return "", err
  115. }
  116. imageID := IDFromDigest(dgst)
  117. is.Lock()
  118. defer is.Unlock()
  119. if _, exists := is.images[imageID]; exists {
  120. return imageID, nil
  121. }
  122. layerID := img.RootFS.ChainID()
  123. var l layer.Layer
  124. if layerID != "" {
  125. l, err = is.ls.Get(layerID)
  126. if err != nil {
  127. return "", err
  128. }
  129. }
  130. imageMeta := &imageMeta{
  131. layer: l,
  132. children: make(map[ID]struct{}),
  133. }
  134. is.images[imageID] = imageMeta
  135. if err := is.digestSet.Add(imageID.Digest()); err != nil {
  136. delete(is.images, imageID)
  137. return "", err
  138. }
  139. return imageID, nil
  140. }
  141. func (is *store) Search(term string) (ID, error) {
  142. is.Lock()
  143. defer is.Unlock()
  144. dgst, err := is.digestSet.Lookup(term)
  145. if err != nil {
  146. if err == digestset.ErrDigestNotFound {
  147. err = fmt.Errorf("No such image: %s", term)
  148. }
  149. return "", err
  150. }
  151. return IDFromDigest(dgst), nil
  152. }
  153. func (is *store) Get(id ID) (*Image, error) {
  154. // todo: Check if image is in images
  155. // todo: Detect manual insertions and start using them
  156. config, err := is.fs.Get(id.Digest())
  157. if err != nil {
  158. return nil, err
  159. }
  160. img, err := NewFromJSON(config)
  161. if err != nil {
  162. return nil, err
  163. }
  164. img.computedID = id
  165. img.Parent, err = is.GetParent(id)
  166. if err != nil {
  167. img.Parent = ""
  168. }
  169. return img, nil
  170. }
  171. func (is *store) Delete(id ID) ([]layer.Metadata, error) {
  172. is.Lock()
  173. defer is.Unlock()
  174. imageMeta := is.images[id]
  175. if imageMeta == nil {
  176. return nil, fmt.Errorf("unrecognized image ID %s", id.String())
  177. }
  178. for id := range imageMeta.children {
  179. is.fs.DeleteMetadata(id.Digest(), "parent")
  180. }
  181. if parent, err := is.GetParent(id); err == nil && is.images[parent] != nil {
  182. delete(is.images[parent].children, id)
  183. }
  184. if err := is.digestSet.Remove(id.Digest()); err != nil {
  185. logrus.Errorf("error removing %s from digest set: %q", id, err)
  186. }
  187. delete(is.images, id)
  188. is.fs.Delete(id.Digest())
  189. if imageMeta.layer != nil {
  190. return is.ls.Release(imageMeta.layer)
  191. }
  192. return nil, nil
  193. }
  194. func (is *store) SetParent(id, parent ID) error {
  195. is.Lock()
  196. defer is.Unlock()
  197. parentMeta := is.images[parent]
  198. if parentMeta == nil {
  199. return fmt.Errorf("unknown parent image ID %s", parent.String())
  200. }
  201. if parent, err := is.GetParent(id); err == nil && is.images[parent] != nil {
  202. delete(is.images[parent].children, id)
  203. }
  204. parentMeta.children[id] = struct{}{}
  205. return is.fs.SetMetadata(id.Digest(), "parent", []byte(parent))
  206. }
  207. func (is *store) GetParent(id ID) (ID, error) {
  208. d, err := is.fs.GetMetadata(id.Digest(), "parent")
  209. if err != nil {
  210. return "", err
  211. }
  212. return ID(d), nil // todo: validate?
  213. }
  214. func (is *store) Children(id ID) []ID {
  215. is.Lock()
  216. defer is.Unlock()
  217. return is.children(id)
  218. }
  219. func (is *store) children(id ID) []ID {
  220. var ids []ID
  221. if is.images[id] != nil {
  222. for id := range is.images[id].children {
  223. ids = append(ids, id)
  224. }
  225. }
  226. return ids
  227. }
  228. func (is *store) Heads() map[ID]*Image {
  229. return is.imagesMap(false)
  230. }
  231. func (is *store) Map() map[ID]*Image {
  232. return is.imagesMap(true)
  233. }
  234. func (is *store) imagesMap(all bool) map[ID]*Image {
  235. is.Lock()
  236. defer is.Unlock()
  237. images := make(map[ID]*Image)
  238. for id := range is.images {
  239. if !all && len(is.children(id)) > 0 {
  240. continue
  241. }
  242. img, err := is.Get(id)
  243. if err != nil {
  244. logrus.Errorf("invalid image access: %q, error: %q", id, err)
  245. continue
  246. }
  247. images[id] = img
  248. }
  249. return images
  250. }