extensions.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package store
  2. import (
  3. "errors"
  4. "strings"
  5. "github.com/docker/swarmkit/api"
  6. memdb "github.com/hashicorp/go-memdb"
  7. )
  8. const tableExtension = "extension"
  9. func init() {
  10. register(ObjectStoreConfig{
  11. Table: &memdb.TableSchema{
  12. Name: tableExtension,
  13. Indexes: map[string]*memdb.IndexSchema{
  14. indexID: {
  15. Name: indexID,
  16. Unique: true,
  17. Indexer: extensionIndexerByID{},
  18. },
  19. indexName: {
  20. Name: indexName,
  21. Unique: true,
  22. Indexer: extensionIndexerByName{},
  23. },
  24. indexCustom: {
  25. Name: indexCustom,
  26. Indexer: extensionCustomIndexer{},
  27. AllowMissing: true,
  28. },
  29. },
  30. },
  31. Save: func(tx ReadTx, snapshot *api.StoreSnapshot) error {
  32. var err error
  33. snapshot.Extensions, err = FindExtensions(tx, All)
  34. return err
  35. },
  36. Restore: func(tx Tx, snapshot *api.StoreSnapshot) error {
  37. extensions, err := FindExtensions(tx, All)
  38. if err != nil {
  39. return err
  40. }
  41. for _, e := range extensions {
  42. if err := DeleteExtension(tx, e.ID); err != nil {
  43. return err
  44. }
  45. }
  46. for _, e := range snapshot.Extensions {
  47. if err := CreateExtension(tx, e); err != nil {
  48. return err
  49. }
  50. }
  51. return nil
  52. },
  53. ApplyStoreAction: func(tx Tx, sa api.StoreAction) error {
  54. switch v := sa.Target.(type) {
  55. case *api.StoreAction_Extension:
  56. obj := v.Extension
  57. switch sa.Action {
  58. case api.StoreActionKindCreate:
  59. return CreateExtension(tx, obj)
  60. case api.StoreActionKindUpdate:
  61. return UpdateExtension(tx, obj)
  62. case api.StoreActionKindRemove:
  63. return DeleteExtension(tx, obj.ID)
  64. }
  65. }
  66. return errUnknownStoreAction
  67. },
  68. })
  69. }
  70. type extensionEntry struct {
  71. *api.Extension
  72. }
  73. func (e extensionEntry) CopyStoreObject() api.StoreObject {
  74. return extensionEntry{Extension: e.Extension.Copy()}
  75. }
  76. // CreateExtension adds a new extension to the store.
  77. // Returns ErrExist if the ID is already taken.
  78. func CreateExtension(tx Tx, e *api.Extension) error {
  79. // Ensure the name is not already in use.
  80. if tx.lookup(tableExtension, indexName, strings.ToLower(e.Annotations.Name)) != nil {
  81. return ErrNameConflict
  82. }
  83. // It can't conflict with built-in kinds either.
  84. if _, ok := schema.Tables[e.Annotations.Name]; ok {
  85. return ErrNameConflict
  86. }
  87. return tx.create(tableExtension, extensionEntry{e})
  88. }
  89. // UpdateExtension updates an existing extension in the store.
  90. // Returns ErrNotExist if the object doesn't exist.
  91. func UpdateExtension(tx Tx, e *api.Extension) error {
  92. // TODO(aaronl): For the moment, extensions are immutable
  93. return errors.New("extensions are immutable")
  94. }
  95. // DeleteExtension removes an extension from the store.
  96. // Returns ErrNotExist if the object doesn't exist.
  97. func DeleteExtension(tx Tx, id string) error {
  98. e := tx.get(tableExtension, id)
  99. if e == nil {
  100. return ErrNotExist
  101. }
  102. resources, err := FindResources(tx, ByKind(e.(extensionEntry).Annotations.Name))
  103. if err != nil {
  104. return err
  105. }
  106. if len(resources) != 0 {
  107. return errors.New("cannot delete extension because objects of this type exist in the data store")
  108. }
  109. return tx.delete(tableExtension, id)
  110. }
  111. // GetExtension looks up an extension by ID.
  112. // Returns nil if the object doesn't exist.
  113. func GetExtension(tx ReadTx, id string) *api.Extension {
  114. e := tx.get(tableExtension, id)
  115. if e == nil {
  116. return nil
  117. }
  118. return e.(extensionEntry).Extension
  119. }
  120. // FindExtensions selects a set of extensions and returns them.
  121. func FindExtensions(tx ReadTx, by By) ([]*api.Extension, error) {
  122. checkType := func(by By) error {
  123. switch by.(type) {
  124. case byIDPrefix, byName, byCustom, byCustomPrefix:
  125. return nil
  126. default:
  127. return ErrInvalidFindBy
  128. }
  129. }
  130. extensionList := []*api.Extension{}
  131. appendResult := func(o api.StoreObject) {
  132. extensionList = append(extensionList, o.(extensionEntry).Extension)
  133. }
  134. err := tx.find(tableExtension, by, checkType, appendResult)
  135. return extensionList, err
  136. }
  137. type extensionIndexerByID struct{}
  138. func (indexer extensionIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
  139. return api.ExtensionIndexerByID{}.FromArgs(args...)
  140. }
  141. func (indexer extensionIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
  142. return api.ExtensionIndexerByID{}.PrefixFromArgs(args...)
  143. }
  144. func (indexer extensionIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
  145. return api.ExtensionIndexerByID{}.FromObject(obj.(extensionEntry).Extension)
  146. }
  147. type extensionIndexerByName struct{}
  148. func (indexer extensionIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
  149. return api.ExtensionIndexerByName{}.FromArgs(args...)
  150. }
  151. func (indexer extensionIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
  152. return api.ExtensionIndexerByName{}.PrefixFromArgs(args...)
  153. }
  154. func (indexer extensionIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
  155. return api.ExtensionIndexerByName{}.FromObject(obj.(extensionEntry).Extension)
  156. }
  157. type extensionCustomIndexer struct{}
  158. func (indexer extensionCustomIndexer) FromArgs(args ...interface{}) ([]byte, error) {
  159. return api.ExtensionCustomIndexer{}.FromArgs(args...)
  160. }
  161. func (indexer extensionCustomIndexer) PrefixFromArgs(args ...interface{}) ([]byte, error) {
  162. return api.ExtensionCustomIndexer{}.PrefixFromArgs(args...)
  163. }
  164. func (indexer extensionCustomIndexer) FromObject(obj interface{}) (bool, [][]byte, error) {
  165. return api.ExtensionCustomIndexer{}.FromObject(obj.(extensionEntry).Extension)
  166. }