github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/state/store/extensions.go (about)

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