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

     1  package manager
     2  
     3  import (
     4  	"reflect"
     5  
     6  	"github.com/docker/swarmkit/api"
     7  	"github.com/docker/swarmkit/manager/state/store"
     8  )
     9  
    10  // IsStateDirty returns true if any objects have been added to raft which make
    11  // the state "dirty". Currently, the existence of any object other than the
    12  // default cluster or the local node implies a dirty state.
    13  func (m *Manager) IsStateDirty() (bool, error) {
    14  	var (
    15  		storeSnapshot *api.StoreSnapshot
    16  		err           error
    17  	)
    18  	m.raftNode.MemoryStore().View(func(readTx store.ReadTx) {
    19  		storeSnapshot, err = m.raftNode.MemoryStore().Save(readTx)
    20  	})
    21  
    22  	if err != nil {
    23  		return false, err
    24  	}
    25  
    26  	// Check Nodes and Clusters fields.
    27  	nodeID := m.config.SecurityConfig.ClientTLSCreds.NodeID()
    28  	if len(storeSnapshot.Nodes) > 1 || (len(storeSnapshot.Nodes) == 1 && storeSnapshot.Nodes[0].ID != nodeID) {
    29  		return true, nil
    30  	}
    31  
    32  	clusterID := m.config.SecurityConfig.ClientTLSCreds.Organization()
    33  	if len(storeSnapshot.Clusters) > 1 || (len(storeSnapshot.Clusters) == 1 && storeSnapshot.Clusters[0].ID != clusterID) {
    34  		return true, nil
    35  	}
    36  
    37  	// Use reflection to check that other fields don't have values. This
    38  	// lets us implement a whitelist-type approach, where we don't need to
    39  	// remember to add individual types here.
    40  
    41  	val := reflect.ValueOf(*storeSnapshot)
    42  	numFields := val.NumField()
    43  
    44  	for i := 0; i != numFields; i++ {
    45  		field := val.Field(i)
    46  		structField := val.Type().Field(i)
    47  		if structField.Type.Kind() != reflect.Slice {
    48  			panic("unexpected field type in StoreSnapshot")
    49  		}
    50  		if structField.Name != "Nodes" && structField.Name != "Clusters" && structField.Name != "Networks" && field.Len() != 0 {
    51  			// One of the other data types has an entry
    52  			return true, nil
    53  		}
    54  	}
    55  
    56  	return false, nil
    57  }