equality.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. package equality
  2. import (
  3. "crypto/subtle"
  4. "reflect"
  5. "github.com/docker/swarmkit/api"
  6. )
  7. // TasksEqualStable returns true if the tasks are functionally equal, ignoring status,
  8. // version and other superfluous fields.
  9. //
  10. // This used to decide whether or not to propagate a task update to a controller.
  11. func TasksEqualStable(a, b *api.Task) bool {
  12. // shallow copy
  13. copyA, copyB := *a, *b
  14. copyA.Status, copyB.Status = api.TaskStatus{}, api.TaskStatus{}
  15. copyA.Meta, copyB.Meta = api.Meta{}, api.Meta{}
  16. return reflect.DeepEqual(&copyA, &copyB)
  17. }
  18. // TaskStatusesEqualStable compares the task status excluding timestamp fields.
  19. func TaskStatusesEqualStable(a, b *api.TaskStatus) bool {
  20. copyA, copyB := *a, *b
  21. copyA.Timestamp, copyB.Timestamp = nil, nil
  22. return reflect.DeepEqual(&copyA, &copyB)
  23. }
  24. // RootCAEqualStable compares RootCAs, excluding join tokens, which are randomly generated
  25. func RootCAEqualStable(a, b *api.RootCA) bool {
  26. if a == nil && b == nil {
  27. return true
  28. }
  29. if a == nil || b == nil {
  30. return false
  31. }
  32. var aRotationKey, bRotationKey []byte
  33. if a.RootRotation != nil {
  34. aRotationKey = a.RootRotation.CAKey
  35. }
  36. if b.RootRotation != nil {
  37. bRotationKey = b.RootRotation.CAKey
  38. }
  39. if subtle.ConstantTimeCompare(a.CAKey, b.CAKey) != 1 || subtle.ConstantTimeCompare(aRotationKey, bRotationKey) != 1 {
  40. return false
  41. }
  42. copyA, copyB := *a, *b
  43. copyA.JoinTokens, copyB.JoinTokens = api.JoinTokens{}, api.JoinTokens{}
  44. return reflect.DeepEqual(copyA, copyB)
  45. }
  46. // ExternalCAsEqualStable compares lists of external CAs and determines whether they are equal.
  47. func ExternalCAsEqualStable(a, b []*api.ExternalCA) bool {
  48. // because DeepEqual will treat an empty list and a nil list differently, we want to manually check this first
  49. if len(a) == 0 && len(b) == 0 {
  50. return true
  51. }
  52. // The assumption is that each individual api.ExternalCA within both lists are created from deserializing from a
  53. // protobuf, so no special affordances are made to treat a nil map and empty map in the Options field of an
  54. // api.ExternalCA as equivalent.
  55. return reflect.DeepEqual(a, b)
  56. }