baf886c6f3
The gist here is that now we use a value-type struct proxycfg.UpstreamID as the map key in ConfigSnapshot maps where we used to use "upstream id-ish" strings. These are internal only and used just for bidirectional trips through the agent cache keyspace (like the discovery chain target struct). For the few places where the upstream id needs to be projected into xDS, that's what (proxycfg.UpstreamID).EnvoyID() is for. This lets us ALWAYS inject the partition and namespace into these things without making stuff like the golden testdata diverge.
131 lines
3.1 KiB
Go
131 lines
3.1 KiB
Go
package proxycfg
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/hashicorp/consul/agent/structs"
|
|
)
|
|
|
|
type UpstreamID struct {
|
|
Type string
|
|
Name string
|
|
Datacenter string
|
|
structs.EnterpriseMeta
|
|
}
|
|
|
|
func NewUpstreamID(u *structs.Upstream) UpstreamID {
|
|
id := UpstreamID{
|
|
Type: u.DestinationType,
|
|
Name: u.DestinationName,
|
|
Datacenter: u.Datacenter,
|
|
EnterpriseMeta: structs.NewEnterpriseMetaWithPartition(
|
|
u.DestinationPartition,
|
|
u.DestinationNamespace,
|
|
),
|
|
}
|
|
id.normalize()
|
|
return id
|
|
}
|
|
|
|
func NewUpstreamIDFromServiceName(sn structs.ServiceName) UpstreamID {
|
|
id := UpstreamID{
|
|
Name: sn.Name,
|
|
EnterpriseMeta: sn.EnterpriseMeta,
|
|
}
|
|
id.normalize()
|
|
return id
|
|
}
|
|
|
|
func NewUpstreamIDFromServiceID(sid structs.ServiceID) UpstreamID {
|
|
id := UpstreamID{
|
|
Name: sid.ID,
|
|
EnterpriseMeta: sid.EnterpriseMeta,
|
|
}
|
|
id.normalize()
|
|
return id
|
|
}
|
|
|
|
func (u *UpstreamID) normalize() {
|
|
if u.Type == structs.UpstreamDestTypeService {
|
|
u.Type = ""
|
|
}
|
|
|
|
u.EnterpriseMeta.Normalize()
|
|
}
|
|
|
|
// String encodes the UpstreamID into a string for use in agent cache keys.
|
|
// You can decode it back again using UpstreamIDFromString.
|
|
func (u UpstreamID) String() string {
|
|
return UpstreamIDString(u.Type, u.Datacenter, u.Name, &u.EnterpriseMeta)
|
|
}
|
|
|
|
func (u UpstreamID) GoString() string {
|
|
return u.String()
|
|
}
|
|
|
|
func UpstreamIDFromString(input string) UpstreamID {
|
|
typ, dc, name, entMeta := ParseUpstreamIDString(input)
|
|
id := UpstreamID{
|
|
Type: typ,
|
|
Datacenter: dc,
|
|
Name: name,
|
|
EnterpriseMeta: *entMeta,
|
|
}
|
|
id.normalize()
|
|
return id
|
|
}
|
|
|
|
const upstreamTypePreparedQueryPrefix = structs.UpstreamDestTypePreparedQuery + ":"
|
|
|
|
func ParseUpstreamIDString(input string) (typ, dc, name string, meta *structs.EnterpriseMeta) {
|
|
if strings.HasPrefix(input, upstreamTypePreparedQueryPrefix) {
|
|
typ = structs.UpstreamDestTypePreparedQuery
|
|
input = strings.TrimPrefix(input, upstreamTypePreparedQueryPrefix)
|
|
}
|
|
|
|
idx := strings.LastIndex(input, "?dc=")
|
|
if idx != -1 {
|
|
dc = input[idx+4:]
|
|
input = input[0:idx]
|
|
}
|
|
|
|
name, meta = parseInnerUpstreamIDString(input)
|
|
|
|
return typ, dc, name, meta
|
|
}
|
|
|
|
// EnvoyID returns a string representation that uniquely identifies the
|
|
// upstream in a canonical but human readable way.
|
|
//
|
|
// This should be used for any situation where we generate identifiers in Envoy
|
|
// xDS structures for this upstream.
|
|
//
|
|
// This will ensure that generated identifiers for the same thing in OSS and
|
|
// Enterprise render the same and omit default namespaces and partitions.
|
|
func (u UpstreamID) EnvoyID() string {
|
|
name := u.enterpriseIdentifierPrefix() + u.Name
|
|
typ := u.Type
|
|
|
|
if u.Datacenter != "" {
|
|
name += "?dc=" + u.Datacenter
|
|
}
|
|
|
|
// Service is default type so never prefix it. This is more readable and long
|
|
// term it is the only type that matters so we can drop the prefix and have
|
|
// nicer naming in metrics etc.
|
|
if typ == "" || typ == structs.UpstreamDestTypeService {
|
|
return name
|
|
}
|
|
return typ + ":" + name
|
|
}
|
|
|
|
func UpstreamsToMap(us structs.Upstreams) map[UpstreamID]*structs.Upstream {
|
|
upstreamMap := make(map[UpstreamID]*structs.Upstream)
|
|
|
|
for i := range us {
|
|
u := us[i]
|
|
upstreamMap[NewUpstreamID(&u)] = &u
|
|
}
|
|
return upstreamMap
|
|
}
|