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 }