123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 |
- package manager
- import (
- "reflect"
- "github.com/docker/swarmkit/api"
- "github.com/docker/swarmkit/manager/state/store"
- )
- // IsStateDirty returns true if any objects have been added to raft which make
- // the state "dirty". Currently, the existence of any object other than the
- // default cluster or the local node implies a dirty state.
- func (m *Manager) IsStateDirty() (bool, error) {
- var (
- storeSnapshot *api.StoreSnapshot
- err error
- )
- m.raftNode.MemoryStore().View(func(readTx store.ReadTx) {
- storeSnapshot, err = m.raftNode.MemoryStore().Save(readTx)
- })
- if err != nil {
- return false, err
- }
- // Check Nodes and Clusters fields.
- nodeID := m.config.SecurityConfig.ClientTLSCreds.NodeID()
- if len(storeSnapshot.Nodes) > 1 || (len(storeSnapshot.Nodes) == 1 && storeSnapshot.Nodes[0].ID != nodeID) {
- return true, nil
- }
- clusterID := m.config.SecurityConfig.ClientTLSCreds.Organization()
- if len(storeSnapshot.Clusters) > 1 || (len(storeSnapshot.Clusters) == 1 && storeSnapshot.Clusters[0].ID != clusterID) {
- return true, nil
- }
- // Use reflection to check that other fields don't have values. This
- // lets us implement a whitelist-type approach, where we don't need to
- // remember to add individual types here.
- val := reflect.ValueOf(*storeSnapshot)
- numFields := val.NumField()
- for i := 0; i != numFields; i++ {
- field := val.Field(i)
- structField := val.Type().Field(i)
- if structField.Type.Kind() != reflect.Slice {
- panic("unexpected field type in StoreSnapshot")
- }
- if structField.Name != "Nodes" && structField.Name != "Clusters" && structField.Name != "Networks" && field.Len() != 0 {
- // One of the other data types has an entry
- return true, nil
- }
- }
- return false, nil
- }
|