open-consul/agent/consul/state/events.go
Daniel Upton 21ea217b1d proxycfg: server-local intentions data source
This is the OSS portion of enterprise PR 2141.

This commit provides a server-local implementation of the `proxycfg.Intentions`
interface that sources data from streaming events.

It adds events for the `service-intentions` config entry type, and then consumes
event streams (via materialized views) for the service's explicit intentions and
any applicable wildcard intentions, merging them into a single list of intentions.

An alternative approach I considered was to consume _all_ intention events (via
`SubjectWildcard`) and filter out the irrelevant ones. This would admittedly
remove some complexity in the `agent/proxycfg-glue` package but at the expense
of considerable overhead from waking potentially many thousands of connect
proxies every time any intention is updated.
2022-07-04 10:48:36 +01:00

58 lines
1.7 KiB
Go

package state
import (
"errors"
"fmt"
"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/agent/consul/stream"
"github.com/hashicorp/consul/proto/pbsubscribe"
)
func PBToStreamSubscribeRequest(req *pbsubscribe.SubscribeRequest, entMeta acl.EnterpriseMeta) (*stream.SubscribeRequest, error) {
var subject stream.Subject
if req.GetWildcardSubject() {
subject = stream.SubjectWildcard
} else {
named := req.GetNamedSubject()
// Support the (deprcated) top-level Key, Partition, Namespace, and PeerName fields.
if named == nil {
named = &pbsubscribe.NamedSubject{
Key: req.Key, // nolint:staticcheck // SA1019 intentional use of deprecated field
Partition: req.Partition, // nolint:staticcheck // SA1019 intentional use of deprecated field
Namespace: req.Namespace, // nolint:staticcheck // SA1019 intentional use of deprecated field
PeerName: req.PeerName, // nolint:staticcheck // SA1019 intentional use of deprecated field
}
}
if named.Key == "" {
return nil, errors.New("either WildcardSubject or NamedSubject.Key is required")
}
switch req.Topic {
case EventTopicServiceHealth, EventTopicServiceHealthConnect:
subject = EventSubjectService{
Key: named.Key,
EnterpriseMeta: entMeta,
PeerName: named.PeerName,
}
case EventTopicMeshConfig, EventTopicServiceResolver, EventTopicIngressGateway, EventTopicServiceIntentions:
subject = EventSubjectConfigEntry{
Name: named.Key,
EnterpriseMeta: &entMeta,
}
default:
return nil, fmt.Errorf("cannot construct subject for topic %s", req.Topic)
}
}
return &stream.SubscribeRequest{
Topic: req.Topic,
Subject: subject,
Token: req.Token,
Index: req.Index,
}, nil
}