123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- package store
- import (
- "strings"
- "github.com/docker/swarmkit/api"
- "github.com/docker/swarmkit/api/naming"
- memdb "github.com/hashicorp/go-memdb"
- )
- const tableService = "service"
- func init() {
- register(ObjectStoreConfig{
- Table: &memdb.TableSchema{
- Name: tableService,
- Indexes: map[string]*memdb.IndexSchema{
- indexID: {
- Name: indexID,
- Unique: true,
- Indexer: api.ServiceIndexerByID{},
- },
- indexName: {
- Name: indexName,
- Unique: true,
- Indexer: api.ServiceIndexerByName{},
- },
- indexRuntime: {
- Name: indexRuntime,
- AllowMissing: true,
- Indexer: serviceIndexerByRuntime{},
- },
- indexNetwork: {
- Name: indexNetwork,
- AllowMissing: true,
- Indexer: serviceIndexerByNetwork{},
- },
- indexSecret: {
- Name: indexSecret,
- AllowMissing: true,
- Indexer: serviceIndexerBySecret{},
- },
- indexConfig: {
- Name: indexConfig,
- AllowMissing: true,
- Indexer: serviceIndexerByConfig{},
- },
- indexCustom: {
- Name: indexCustom,
- Indexer: api.ServiceCustomIndexer{},
- AllowMissing: true,
- },
- },
- },
- Save: func(tx ReadTx, snapshot *api.StoreSnapshot) error {
- var err error
- snapshot.Services, err = FindServices(tx, All)
- return err
- },
- Restore: func(tx Tx, snapshot *api.StoreSnapshot) error {
- services, err := FindServices(tx, All)
- if err != nil {
- return err
- }
- for _, s := range services {
- if err := DeleteService(tx, s.ID); err != nil {
- return err
- }
- }
- for _, s := range snapshot.Services {
- if err := CreateService(tx, s); err != nil {
- return err
- }
- }
- return nil
- },
- ApplyStoreAction: func(tx Tx, sa api.StoreAction) error {
- switch v := sa.Target.(type) {
- case *api.StoreAction_Service:
- obj := v.Service
- switch sa.Action {
- case api.StoreActionKindCreate:
- return CreateService(tx, obj)
- case api.StoreActionKindUpdate:
- return UpdateService(tx, obj)
- case api.StoreActionKindRemove:
- return DeleteService(tx, obj.ID)
- }
- }
- return errUnknownStoreAction
- },
- })
- }
- // CreateService adds a new service to the store.
- // Returns ErrExist if the ID is already taken.
- func CreateService(tx Tx, s *api.Service) error {
- // Ensure the name is not already in use.
- if tx.lookup(tableService, indexName, strings.ToLower(s.Spec.Annotations.Name)) != nil {
- return ErrNameConflict
- }
- return tx.create(tableService, s)
- }
- // UpdateService updates an existing service in the store.
- // Returns ErrNotExist if the service doesn't exist.
- func UpdateService(tx Tx, s *api.Service) error {
- // Ensure the name is either not in use or already used by this same Service.
- if existing := tx.lookup(tableService, indexName, strings.ToLower(s.Spec.Annotations.Name)); existing != nil {
- if existing.GetID() != s.ID {
- return ErrNameConflict
- }
- }
- return tx.update(tableService, s)
- }
- // DeleteService removes a service from the store.
- // Returns ErrNotExist if the service doesn't exist.
- func DeleteService(tx Tx, id string) error {
- return tx.delete(tableService, id)
- }
- // GetService looks up a service by ID.
- // Returns nil if the service doesn't exist.
- func GetService(tx ReadTx, id string) *api.Service {
- s := tx.get(tableService, id)
- if s == nil {
- return nil
- }
- return s.(*api.Service)
- }
- // FindServices selects a set of services and returns them.
- func FindServices(tx ReadTx, by By) ([]*api.Service, error) {
- checkType := func(by By) error {
- switch by.(type) {
- case byName, byNamePrefix, byIDPrefix, byRuntime, byReferencedNetworkID, byReferencedSecretID, byReferencedConfigID, byCustom, byCustomPrefix:
- return nil
- default:
- return ErrInvalidFindBy
- }
- }
- serviceList := []*api.Service{}
- appendResult := func(o api.StoreObject) {
- serviceList = append(serviceList, o.(*api.Service))
- }
- err := tx.find(tableService, by, checkType, appendResult)
- return serviceList, err
- }
- type serviceIndexerByRuntime struct{}
- func (si serviceIndexerByRuntime) FromArgs(args ...interface{}) ([]byte, error) {
- return fromArgs(args...)
- }
- func (si serviceIndexerByRuntime) FromObject(obj interface{}) (bool, []byte, error) {
- s := obj.(*api.Service)
- r, err := naming.Runtime(s.Spec.Task)
- if err != nil {
- return false, nil, nil
- }
- return true, []byte(r + "\x00"), nil
- }
- func (si serviceIndexerByRuntime) PrefixFromArgs(args ...interface{}) ([]byte, error) {
- return prefixFromArgs(args...)
- }
- type serviceIndexerByNetwork struct{}
- func (si serviceIndexerByNetwork) FromArgs(args ...interface{}) ([]byte, error) {
- return fromArgs(args...)
- }
- func (si serviceIndexerByNetwork) FromObject(obj interface{}) (bool, [][]byte, error) {
- s := obj.(*api.Service)
- var networkIDs [][]byte
- specNetworks := s.Spec.Task.Networks
- if len(specNetworks) == 0 {
- specNetworks = s.Spec.Networks
- }
- for _, na := range specNetworks {
- // Add the null character as a terminator
- networkIDs = append(networkIDs, []byte(na.Target+"\x00"))
- }
- return len(networkIDs) != 0, networkIDs, nil
- }
- type serviceIndexerBySecret struct{}
- func (si serviceIndexerBySecret) FromArgs(args ...interface{}) ([]byte, error) {
- return fromArgs(args...)
- }
- func (si serviceIndexerBySecret) FromObject(obj interface{}) (bool, [][]byte, error) {
- s := obj.(*api.Service)
- container := s.Spec.Task.GetContainer()
- if container == nil {
- return false, nil, nil
- }
- var secretIDs [][]byte
- for _, secretRef := range container.Secrets {
- // Add the null character as a terminator
- secretIDs = append(secretIDs, []byte(secretRef.SecretID+"\x00"))
- }
- return len(secretIDs) != 0, secretIDs, nil
- }
- type serviceIndexerByConfig struct{}
- func (si serviceIndexerByConfig) FromArgs(args ...interface{}) ([]byte, error) {
- return fromArgs(args...)
- }
- func (si serviceIndexerByConfig) FromObject(obj interface{}) (bool, [][]byte, error) {
- s, ok := obj.(*api.Service)
- if !ok {
- panic("unexpected type passed to FromObject")
- }
- container := s.Spec.Task.GetContainer()
- if container == nil {
- return false, nil, nil
- }
- var configIDs [][]byte
- for _, configRef := range container.Configs {
- // Add the null character as a terminator
- configIDs = append(configIDs, []byte(configRef.ConfigID+"\x00"))
- }
- return len(configIDs) != 0, configIDs, nil
- }
|