123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- package store
- import (
- "github.com/docker/swarmkit/api"
- memdb "github.com/hashicorp/go-memdb"
- "github.com/pkg/errors"
- )
- const tableResource = "resource"
- func init() {
- register(ObjectStoreConfig{
- Table: &memdb.TableSchema{
- Name: tableResource,
- Indexes: map[string]*memdb.IndexSchema{
- indexID: {
- Name: indexID,
- Unique: true,
- Indexer: resourceIndexerByID{},
- },
- indexName: {
- Name: indexName,
- Unique: true,
- Indexer: resourceIndexerByName{},
- },
- indexKind: {
- Name: indexKind,
- Indexer: resourceIndexerByKind{},
- },
- indexCustom: {
- Name: indexCustom,
- Indexer: resourceCustomIndexer{},
- AllowMissing: true,
- },
- },
- },
- Save: func(tx ReadTx, snapshot *api.StoreSnapshot) error {
- var err error
- snapshot.Resources, err = FindResources(tx, All)
- return err
- },
- Restore: func(tx Tx, snapshot *api.StoreSnapshot) error {
- resources, err := FindResources(tx, All)
- if err != nil {
- return err
- }
- for _, r := range resources {
- if err := DeleteResource(tx, r.ID); err != nil {
- return err
- }
- }
- for _, r := range snapshot.Resources {
- if err := CreateResource(tx, r); err != nil {
- return err
- }
- }
- return nil
- },
- ApplyStoreAction: func(tx Tx, sa api.StoreAction) error {
- switch v := sa.Target.(type) {
- case *api.StoreAction_Resource:
- obj := v.Resource
- switch sa.Action {
- case api.StoreActionKindCreate:
- return CreateResource(tx, obj)
- case api.StoreActionKindUpdate:
- return UpdateResource(tx, obj)
- case api.StoreActionKindRemove:
- return DeleteResource(tx, obj.ID)
- }
- }
- return errUnknownStoreAction
- },
- })
- }
- type resourceEntry struct {
- *api.Resource
- }
- func (r resourceEntry) CopyStoreObject() api.StoreObject {
- return resourceEntry{Resource: r.Resource.Copy()}
- }
- func confirmExtension(tx Tx, r *api.Resource) error {
- // There must be an extension corresponding to the Kind field.
- extensions, err := FindExtensions(tx, ByName(r.Kind))
- if err != nil {
- return errors.Wrap(err, "failed to query extensions")
- }
- if len(extensions) == 0 {
- return errors.Errorf("object kind %s is unregistered", r.Kind)
- }
- return nil
- }
- // CreateResource adds a new resource object to the store.
- // Returns ErrExist if the ID is already taken.
- func CreateResource(tx Tx, r *api.Resource) error {
- if err := confirmExtension(tx, r); err != nil {
- return err
- }
- return tx.create(tableResource, resourceEntry{r})
- }
- // UpdateResource updates an existing resource object in the store.
- // Returns ErrNotExist if the object doesn't exist.
- func UpdateResource(tx Tx, r *api.Resource) error {
- if err := confirmExtension(tx, r); err != nil {
- return err
- }
- return tx.update(tableResource, resourceEntry{r})
- }
- // DeleteResource removes a resource object from the store.
- // Returns ErrNotExist if the object doesn't exist.
- func DeleteResource(tx Tx, id string) error {
- return tx.delete(tableResource, id)
- }
- // GetResource looks up a resource object by ID.
- // Returns nil if the object doesn't exist.
- func GetResource(tx ReadTx, id string) *api.Resource {
- r := tx.get(tableResource, id)
- if r == nil {
- return nil
- }
- return r.(resourceEntry).Resource
- }
- // FindResources selects a set of resource objects and returns them.
- func FindResources(tx ReadTx, by By) ([]*api.Resource, error) {
- checkType := func(by By) error {
- switch by.(type) {
- case byIDPrefix, byName, byKind, byCustom, byCustomPrefix:
- return nil
- default:
- return ErrInvalidFindBy
- }
- }
- resourceList := []*api.Resource{}
- appendResult := func(o api.StoreObject) {
- resourceList = append(resourceList, o.(resourceEntry).Resource)
- }
- err := tx.find(tableResource, by, checkType, appendResult)
- return resourceList, err
- }
- type resourceIndexerByKind struct{}
- func (ri resourceIndexerByKind) FromArgs(args ...interface{}) ([]byte, error) {
- return fromArgs(args...)
- }
- func (ri resourceIndexerByKind) FromObject(obj interface{}) (bool, []byte, error) {
- r := obj.(resourceEntry)
- // Add the null character as a terminator
- val := r.Resource.Kind + "\x00"
- return true, []byte(val), nil
- }
- type resourceIndexerByID struct{}
- func (indexer resourceIndexerByID) FromArgs(args ...interface{}) ([]byte, error) {
- return api.ResourceIndexerByID{}.FromArgs(args...)
- }
- func (indexer resourceIndexerByID) PrefixFromArgs(args ...interface{}) ([]byte, error) {
- return api.ResourceIndexerByID{}.PrefixFromArgs(args...)
- }
- func (indexer resourceIndexerByID) FromObject(obj interface{}) (bool, []byte, error) {
- return api.ResourceIndexerByID{}.FromObject(obj.(resourceEntry).Resource)
- }
- type resourceIndexerByName struct{}
- func (indexer resourceIndexerByName) FromArgs(args ...interface{}) ([]byte, error) {
- return api.ResourceIndexerByName{}.FromArgs(args...)
- }
- func (indexer resourceIndexerByName) PrefixFromArgs(args ...interface{}) ([]byte, error) {
- return api.ResourceIndexerByName{}.PrefixFromArgs(args...)
- }
- func (indexer resourceIndexerByName) FromObject(obj interface{}) (bool, []byte, error) {
- return api.ResourceIndexerByName{}.FromObject(obj.(resourceEntry).Resource)
- }
- type resourceCustomIndexer struct{}
- func (indexer resourceCustomIndexer) FromArgs(args ...interface{}) ([]byte, error) {
- return api.ResourceCustomIndexer{}.FromArgs(args...)
- }
- func (indexer resourceCustomIndexer) PrefixFromArgs(args ...interface{}) ([]byte, error) {
- return api.ResourceCustomIndexer{}.PrefixFromArgs(args...)
- }
- func (indexer resourceCustomIndexer) FromObject(obj interface{}) (bool, [][]byte, error) {
- return api.ResourceCustomIndexer{}.FromObject(obj.(resourceEntry).Resource)
- }
|