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

     1  package store
     2  
     3  import (
     4  	"strconv"
     5  	"strings"
     6  
     7  	"github.com/docker/swarmkit/api"
     8  	memdb "github.com/hashicorp/go-memdb"
     9  )
    10  
    11  const tableNode = "node"
    12  
    13  func init() {
    14  	register(ObjectStoreConfig{
    15  		Table: &memdb.TableSchema{
    16  			Name: tableNode,
    17  			Indexes: map[string]*memdb.IndexSchema{
    18  				indexID: {
    19  					Name:    indexID,
    20  					Unique:  true,
    21  					Indexer: api.NodeIndexerByID{},
    22  				},
    23  				// TODO(aluzzardi): Use `indexHostname` instead.
    24  				indexName: {
    25  					Name:         indexName,
    26  					AllowMissing: true,
    27  					Indexer:      nodeIndexerByHostname{},
    28  				},
    29  				indexRole: {
    30  					Name:    indexRole,
    31  					Indexer: nodeIndexerByRole{},
    32  				},
    33  				indexMembership: {
    34  					Name:    indexMembership,
    35  					Indexer: nodeIndexerByMembership{},
    36  				},
    37  				indexCustom: {
    38  					Name:         indexCustom,
    39  					Indexer:      api.NodeCustomIndexer{},
    40  					AllowMissing: true,
    41  				},
    42  			},
    43  		},
    44  		Save: func(tx ReadTx, snapshot *api.StoreSnapshot) error {
    45  			var err error
    46  			snapshot.Nodes, err = FindNodes(tx, All)
    47  			return err
    48  		},
    49  		Restore: func(tx Tx, snapshot *api.StoreSnapshot) error {
    50  			toStoreObj := make([]api.StoreObject, len(snapshot.Nodes))
    51  			for i, x := range snapshot.Nodes {
    52  				toStoreObj[i] = x
    53  			}
    54  			return RestoreTable(tx, tableNode, toStoreObj)
    55  		},
    56  		ApplyStoreAction: func(tx Tx, sa api.StoreAction) error {
    57  			switch v := sa.Target.(type) {
    58  			case *api.StoreAction_Node:
    59  				obj := v.Node
    60  				switch sa.Action {
    61  				case api.StoreActionKindCreate:
    62  					return CreateNode(tx, obj)
    63  				case api.StoreActionKindUpdate:
    64  					return UpdateNode(tx, obj)
    65  				case api.StoreActionKindRemove:
    66  					return DeleteNode(tx, obj.ID)
    67  				}
    68  			}
    69  			return errUnknownStoreAction
    70  		},
    71  	})
    72  }
    73  
    74  // CreateNode adds a new node to the store.
    75  // Returns ErrExist if the ID is already taken.
    76  func CreateNode(tx Tx, n *api.Node) error {
    77  	return tx.create(tableNode, n)
    78  }
    79  
    80  // UpdateNode updates an existing node in the store.
    81  // Returns ErrNotExist if the node doesn't exist.
    82  func UpdateNode(tx Tx, n *api.Node) error {
    83  	return tx.update(tableNode, n)
    84  }
    85  
    86  // DeleteNode removes a node from the store.
    87  // Returns ErrNotExist if the node doesn't exist.
    88  func DeleteNode(tx Tx, id string) error {
    89  	return tx.delete(tableNode, id)
    90  }
    91  
    92  // GetNode looks up a node by ID.
    93  // Returns nil if the node doesn't exist.
    94  func GetNode(tx ReadTx, id string) *api.Node {
    95  	n := tx.get(tableNode, id)
    96  	if n == nil {
    97  		return nil
    98  	}
    99  	return n.(*api.Node)
   100  }
   101  
   102  // FindNodes selects a set of nodes and returns them.
   103  func FindNodes(tx ReadTx, by By) ([]*api.Node, error) {
   104  	checkType := func(by By) error {
   105  		switch by.(type) {
   106  		case byName, byNamePrefix, byIDPrefix, byRole, byMembership, byCustom, byCustomPrefix:
   107  			return nil
   108  		default:
   109  			return ErrInvalidFindBy
   110  		}
   111  	}
   112  
   113  	nodeList := []*api.Node{}
   114  	appendResult := func(o api.StoreObject) {
   115  		nodeList = append(nodeList, o.(*api.Node))
   116  	}
   117  
   118  	err := tx.find(tableNode, by, checkType, appendResult)
   119  	return nodeList, err
   120  }
   121  
   122  type nodeIndexerByHostname struct{}
   123  
   124  func (ni nodeIndexerByHostname) FromArgs(args ...interface{}) ([]byte, error) {
   125  	return fromArgs(args...)
   126  }
   127  
   128  func (ni nodeIndexerByHostname) FromObject(obj interface{}) (bool, []byte, error) {
   129  	n := obj.(*api.Node)
   130  
   131  	if n.Description == nil {
   132  		return false, nil, nil
   133  	}
   134  	// Add the null character as a terminator
   135  	return true, []byte(strings.ToLower(n.Description.Hostname) + "\x00"), nil
   136  }
   137  
   138  func (ni nodeIndexerByHostname) PrefixFromArgs(args ...interface{}) ([]byte, error) {
   139  	return prefixFromArgs(args...)
   140  }
   141  
   142  type nodeIndexerByRole struct{}
   143  
   144  func (ni nodeIndexerByRole) FromArgs(args ...interface{}) ([]byte, error) {
   145  	return fromArgs(args...)
   146  }
   147  
   148  func (ni nodeIndexerByRole) FromObject(obj interface{}) (bool, []byte, error) {
   149  	n := obj.(*api.Node)
   150  
   151  	// Add the null character as a terminator
   152  	return true, []byte(strconv.FormatInt(int64(n.Role), 10) + "\x00"), nil
   153  }
   154  
   155  type nodeIndexerByMembership struct{}
   156  
   157  func (ni nodeIndexerByMembership) FromArgs(args ...interface{}) ([]byte, error) {
   158  	return fromArgs(args...)
   159  }
   160  
   161  func (ni nodeIndexerByMembership) FromObject(obj interface{}) (bool, []byte, error) {
   162  	n := obj.(*api.Node)
   163  
   164  	// Add the null character as a terminator
   165  	return true, []byte(strconv.FormatInt(int64(n.Spec.Membership), 10) + "\x00"), nil
   166  }