2023-03-28 18:39:22 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
2023-08-11 13:12:13 +00:00
|
|
|
// SPDX-License-Identifier: BUSL-1.1
|
2023-03-28 18:39:22 +00:00
|
|
|
|
2020-03-09 20:59:02 +00:00
|
|
|
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
|
|
|
|
}
|