mirror of https://github.com/hashicorp/consul
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
|
||
|
}
|