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

     1  package store
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/docker/swarmkit/api"
     7  	"github.com/docker/swarmkit/api/naming"
     8  	memdb "github.com/hashicorp/go-memdb"
     9  )
    10  
    11  const tableService = "service"
    12  
    13  func init() {
    14  	register(ObjectStoreConfig{
    15  		Table: &memdb.TableSchema{
    16  			Name: tableService,
    17  			Indexes: map[string]*memdb.IndexSchema{
    18  				indexID: {
    19  					Name:    indexID,
    20  					Unique:  true,
    21  					Indexer: api.ServiceIndexerByID{},
    22  				},
    23  				indexName: {
    24  					Name:    indexName,
    25  					Unique:  true,
    26  					Indexer: api.ServiceIndexerByName{},
    27  				},
    28  				indexRuntime: {
    29  					Name:         indexRuntime,
    30  					AllowMissing: true,
    31  					Indexer:      serviceIndexerByRuntime{},
    32  				},
    33  				indexNetwork: {
    34  					Name:         indexNetwork,
    35  					AllowMissing: true,
    36  					Indexer:      serviceIndexerByNetwork{},
    37  				},
    38  				indexSecret: {
    39  					Name:         indexSecret,
    40  					AllowMissing: true,
    41  					Indexer:      serviceIndexerBySecret{},
    42  				},
    43  				indexConfig: {
    44  					Name:         indexConfig,
    45  					AllowMissing: true,
    46  					Indexer:      serviceIndexerByConfig{},
    47  				},
    48  				indexCustom: {
    49  					Name:         indexCustom,
    50  					Indexer:      api.ServiceCustomIndexer{},
    51  					AllowMissing: true,
    52  				},
    53  			},
    54  		},
    55  		Save: func(tx ReadTx, snapshot *api.StoreSnapshot) error {
    56  			var err error
    57  			snapshot.Services, err = FindServices(tx, All)
    58  			return err
    59  		},
    60  		Restore: func(tx Tx, snapshot *api.StoreSnapshot) error {
    61  			toStoreObj := make([]api.StoreObject, len(snapshot.Services))
    62  			for i, x := range snapshot.Services {
    63  				toStoreObj[i] = x
    64  			}
    65  			return RestoreTable(tx, tableService, toStoreObj)
    66  		},
    67  		ApplyStoreAction: func(tx Tx, sa api.StoreAction) error {
    68  			switch v := sa.Target.(type) {
    69  			case *api.StoreAction_Service:
    70  				obj := v.Service
    71  				switch sa.Action {
    72  				case api.StoreActionKindCreate:
    73  					return CreateService(tx, obj)
    74  				case api.StoreActionKindUpdate:
    75  					return UpdateService(tx, obj)
    76  				case api.StoreActionKindRemove:
    77  					return DeleteService(tx, obj.ID)
    78  				}
    79  			}
    80  			return errUnknownStoreAction
    81  		},
    82  	})
    83  }
    84  
    85  // CreateService adds a new service to the store.
    86  // Returns ErrExist if the ID is already taken.
    87  func CreateService(tx Tx, s *api.Service) error {
    88  	// Ensure the name is not already in use.
    89  	if tx.lookup(tableService, indexName, strings.ToLower(s.Spec.Annotations.Name)) != nil {
    90  		return ErrNameConflict
    91  	}
    92  
    93  	return tx.create(tableService, s)
    94  }
    95  
    96  // UpdateService updates an existing service in the store.
    97  // Returns ErrNotExist if the service doesn't exist.
    98  func UpdateService(tx Tx, s *api.Service) error {
    99  	// Ensure the name is either not in use or already used by this same Service.
   100  	if existing := tx.lookup(tableService, indexName, strings.ToLower(s.Spec.Annotations.Name)); existing != nil {
   101  		if existing.GetID() != s.ID {
   102  			return ErrNameConflict
   103  		}
   104  	}
   105  
   106  	return tx.update(tableService, s)
   107  }
   108  
   109  // DeleteService removes a service from the store.
   110  // Returns ErrNotExist if the service doesn't exist.
   111  func DeleteService(tx Tx, id string) error {
   112  	return tx.delete(tableService, id)
   113  }
   114  
   115  // GetService looks up a service by ID.
   116  // Returns nil if the service doesn't exist.
   117  func GetService(tx ReadTx, id string) *api.Service {
   118  	s := tx.get(tableService, id)
   119  	if s == nil {
   120  		return nil
   121  	}
   122  	return s.(*api.Service)
   123  }
   124  
   125  // FindServices selects a set of services and returns them.
   126  func FindServices(tx ReadTx, by By) ([]*api.Service, error) {
   127  	checkType := func(by By) error {
   128  		switch by.(type) {
   129  		case byName, byNamePrefix, byIDPrefix, byRuntime, byReferencedNetworkID, byReferencedSecretID, byReferencedConfigID, byCustom, byCustomPrefix, byAll:
   130  			return nil
   131  		default:
   132  			return ErrInvalidFindBy
   133  		}
   134  	}
   135  
   136  	serviceList := []*api.Service{}
   137  	appendResult := func(o api.StoreObject) {
   138  		serviceList = append(serviceList, o.(*api.Service))
   139  	}
   140  
   141  	err := tx.find(tableService, by, checkType, appendResult)
   142  	return serviceList, err
   143  }
   144  
   145  type serviceIndexerByRuntime struct{}
   146  
   147  func (si serviceIndexerByRuntime) FromArgs(args ...interface{}) ([]byte, error) {
   148  	return fromArgs(args...)
   149  }
   150  
   151  func (si serviceIndexerByRuntime) FromObject(obj interface{}) (bool, []byte, error) {
   152  	s := obj.(*api.Service)
   153  	r, err := naming.Runtime(s.Spec.Task)
   154  	if err != nil {
   155  		return false, nil, nil
   156  	}
   157  	return true, []byte(r + "\x00"), nil
   158  }
   159  
   160  func (si serviceIndexerByRuntime) PrefixFromArgs(args ...interface{}) ([]byte, error) {
   161  	return prefixFromArgs(args...)
   162  }
   163  
   164  type serviceIndexerByNetwork struct{}
   165  
   166  func (si serviceIndexerByNetwork) FromArgs(args ...interface{}) ([]byte, error) {
   167  	return fromArgs(args...)
   168  }
   169  
   170  func (si serviceIndexerByNetwork) FromObject(obj interface{}) (bool, [][]byte, error) {
   171  	s := obj.(*api.Service)
   172  
   173  	var networkIDs [][]byte
   174  
   175  	specNetworks := s.Spec.Task.Networks
   176  
   177  	if len(specNetworks) == 0 {
   178  		specNetworks = s.Spec.Networks
   179  	}
   180  
   181  	for _, na := range specNetworks {
   182  		// Add the null character as a terminator
   183  		networkIDs = append(networkIDs, []byte(na.Target+"\x00"))
   184  	}
   185  
   186  	return len(networkIDs) != 0, networkIDs, nil
   187  }
   188  
   189  type serviceIndexerBySecret struct{}
   190  
   191  func (si serviceIndexerBySecret) FromArgs(args ...interface{}) ([]byte, error) {
   192  	return fromArgs(args...)
   193  }
   194  
   195  func (si serviceIndexerBySecret) FromObject(obj interface{}) (bool, [][]byte, error) {
   196  	s := obj.(*api.Service)
   197  
   198  	container := s.Spec.Task.GetContainer()
   199  	if container == nil {
   200  		return false, nil, nil
   201  	}
   202  
   203  	var secretIDs [][]byte
   204  
   205  	for _, secretRef := range container.Secrets {
   206  		// Add the null character as a terminator
   207  		secretIDs = append(secretIDs, []byte(secretRef.SecretID+"\x00"))
   208  	}
   209  
   210  	return len(secretIDs) != 0, secretIDs, nil
   211  }
   212  
   213  type serviceIndexerByConfig struct{}
   214  
   215  func (si serviceIndexerByConfig) FromArgs(args ...interface{}) ([]byte, error) {
   216  	return fromArgs(args...)
   217  }
   218  
   219  func (si serviceIndexerByConfig) FromObject(obj interface{}) (bool, [][]byte, error) {
   220  	s, ok := obj.(*api.Service)
   221  	if !ok {
   222  		panic("unexpected type passed to FromObject")
   223  	}
   224  
   225  	container := s.Spec.Task.GetContainer()
   226  	if container == nil {
   227  		return false, nil, nil
   228  	}
   229  
   230  	var configIDs [][]byte
   231  
   232  	for _, configRef := range container.Configs {
   233  		// Add the null character as a terminator
   234  		configIDs = append(configIDs, []byte(configRef.ConfigID+"\x00"))
   235  	}
   236  
   237  	return len(configIDs) != 0, configIDs, nil
   238  }