package structs import ( "sort" "time" ) // FederationStateOp is the operation for a request related to federation states. type FederationStateOp string const ( FederationStateUpsert FederationStateOp = "upsert" FederationStateDelete FederationStateOp = "delete" ) // FederationStateRequest is used to upsert and delete federation states. type FederationStateRequest struct { // Datacenter is the target for this request. Datacenter string // Op is the type of operation being requested. Op FederationStateOp // State is the federation state to upsert or in the case of a delete // only the State.Datacenter field should be set. State *FederationState // WriteRequest is a common struct containing ACL tokens and other // write-related common elements for requests. WriteRequest } // RequestDatacenter returns the datacenter for a given request. func (c *FederationStateRequest) RequestDatacenter() string { return c.Datacenter } // FederationStates is a list of federation states. type FederationStates []*FederationState // Sort sorts federation states by their datacenter. func (listings FederationStates) Sort() { sort.Slice(listings, func(i, j int) bool { return listings[i].Datacenter < listings[j].Datacenter }) } // FederationState defines some WAN federation related state that should be // cross-shared between all datacenters joined on the WAN. One record exists // per datacenter. type FederationState struct { // Datacenter is the name of the datacenter. Datacenter string // MeshGateways is a snapshot of the catalog state for all mesh gateways in // this datacenter. MeshGateways CheckServiceNodes `json:",omitempty"` // UpdatedAt keeps track of when this record was modified. UpdatedAt time.Time // PrimaryModifyIndex is the ModifyIndex of the original data as it exists // in the primary datacenter. PrimaryModifyIndex uint64 // RaftIndex is local raft data. RaftIndex } // IsSame is used to compare two federation states for the purposes of // anti-entropy. func (c *FederationState) IsSame(other *FederationState) bool { if c.Datacenter != other.Datacenter { return false } // We don't include the UpdatedAt field in this comparison because that is // only updated when we re-persist. if len(c.MeshGateways) != len(other.MeshGateways) { return false } // NOTE: we don't bother to sort these since the order is going to be // already defined by how the catalog returns results which should be // stable enough. for i := 0; i < len(c.MeshGateways); i++ { a := c.MeshGateways[i] b := other.MeshGateways[i] if !a.Node.IsSame(b.Node) { return false } if !a.Service.IsSame(b.Service) { return false } if len(a.Checks) != len(b.Checks) { return false } for j := 0; j < len(a.Checks); j++ { ca := a.Checks[j] cb := b.Checks[j] if !ca.IsSame(cb) { return false } } } return true } // FederationStateQuery is used to query federation states. type FederationStateQuery struct { // Datacenter is the target this request is intended for. Datacenter string // TargetDatacenter is the name of a datacenter to fetch the federation state for. TargetDatacenter string // Options for queries QueryOptions } // RequestDatacenter returns the datacenter for a given request. func (c *FederationStateQuery) RequestDatacenter() string { return c.TargetDatacenter } // FederationStateResponse is the response to a FederationStateQuery request. type FederationStateResponse struct { State *FederationState QueryMeta } // IndexedFederationStates represents the list of all federation states. type IndexedFederationStates struct { States FederationStates QueryMeta }