Implement APIGateway proxycfg snapshot (#16194)
* Stub proxycfg handler for API gateway * Add Service Kind constants/handling for API Gateway * Begin stubbing for SDS * Add new Secret type to xDS order of operations * Continue stubbing of SDS * Iterate on proxycfg handler for API gateway * Handle BoundAPIGateway config entry subscription in proxycfg-glue * Add API gateway to config snapshot validation * Add API gateway to config snapshot clone, leaf, etc. * Subscribe to bound route + cert config entries on bound-api-gateway * Track routes + certs on API gateway config snapshot * Generate DeepCopy() for types used in watch.Map * Watch all active references on api-gateway, unwatch inactive * Track loading of initial bound-api-gateway config entry * Use proper proto package for SDS mapping * Use ResourceReference instead of ServiceName, collect resources * Fix typo, add + remove TODOs * Watch discovery chains for TCPRoute * Add TODO for updating gateway services for api-gateway * make proto * Regenerate deep-copy for proxycfg * Set datacenter on upstream ID from query source * Watch discovery chains for http-route service backends * Add ServiceName getter to HTTP+TCP Service structs * Clean up unwatched discovery chains on API Gateway * Implement watch for ingress leaf certificate * Collect upstreams on http-route + tcp-route updates * Remove unused GatewayServices update handler * Remove unnecessary gateway services logic for API Gateway * Remove outdate TODO * Use .ToIngress where appropriate, including TODO for cleaning up * Cancel before returning error * Remove GatewayServices subscription * Add godoc for handlerAPIGateway functions * Update terminology from Connect => Consul Service Mesh Consistent with terminology changes in https://github.com/hashicorp/consul/pull/12690 * Add missing TODO * Remove duplicate switch case * Rerun deep-copy generator * Use correct property on config snapshot * Remove unnecessary leaf cert watch * Clean up based on code review feedback * Note handler properties that are initialized but set elsewhere * Add TODO for moving helper func into structs pkg * Update generated DeepCopy code * gofmt * Generate DeepCopy() for API gateway listener types * Improve variable name * Regenerate DeepCopy() code * Fix linting issue * Temporarily remove the secret type from resource generation
This commit is contained in:
parent
bc7badae9f
commit
423257c473
|
@ -1715,6 +1715,8 @@ func (b *builder) serviceKindVal(v *string) structs.ServiceKind {
|
|||
return structs.ServiceKindTerminatingGateway
|
||||
case string(structs.ServiceKindIngressGateway):
|
||||
return structs.ServiceKindIngressGateway
|
||||
case string(structs.ServiceKindAPIGateway):
|
||||
return structs.ServiceKindAPIGateway
|
||||
default:
|
||||
return structs.ServiceKindTypical
|
||||
}
|
||||
|
|
|
@ -462,9 +462,9 @@ func insertConfigEntryWithTxn(tx WriteTxn, idx uint64, conf structs.ConfigEntry)
|
|||
if conf == nil {
|
||||
return fmt.Errorf("cannot insert nil config entry")
|
||||
}
|
||||
|
||||
// If the config entry is for a terminating or ingress gateway we update the memdb table
|
||||
// that associates gateways <-> services.
|
||||
|
||||
if conf.GetKind() == structs.TerminatingGateway || conf.GetKind() == structs.IngressGateway {
|
||||
err := updateGatewayServices(tx, idx, conf, conf.GetEnterpriseMeta())
|
||||
if err != nil {
|
||||
|
|
|
@ -126,6 +126,8 @@ func convertToResponseServiceKind(serviceKind structs.ServiceKind) (respKind pbd
|
|||
respKind = pbdataplane.ServiceKind_SERVICE_KIND_TERMINATING_GATEWAY
|
||||
case structs.ServiceKindIngressGateway:
|
||||
respKind = pbdataplane.ServiceKind_SERVICE_KIND_INGRESS_GATEWAY
|
||||
case structs.ServiceKindAPIGateway:
|
||||
respKind = pbdataplane.ServiceKind_SERVICE_KIND_API_GATEWAY
|
||||
case structs.ServiceKindTypical:
|
||||
respKind = pbdataplane.ServiceKind_SERVICE_KIND_TYPICAL
|
||||
}
|
||||
|
|
|
@ -0,0 +1,426 @@
|
|||
package proxycfg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/consul/agent/proxycfg/internal/watch"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
"github.com/hashicorp/consul/proto/pbpeering"
|
||||
)
|
||||
|
||||
var _ kindHandler = (*handlerAPIGateway)(nil)
|
||||
|
||||
// handlerAPIGateway generates a new ConfigSnapshot in response to
|
||||
// changes related to an api-gateway.
|
||||
type handlerAPIGateway struct {
|
||||
handlerState
|
||||
}
|
||||
|
||||
// initialize sets up the initial watches needed based on the api-gateway registration
|
||||
func (h *handlerAPIGateway) initialize(ctx context.Context) (ConfigSnapshot, error) {
|
||||
snap := newConfigSnapshotFromServiceInstance(h.serviceInstance, h.stateConfig)
|
||||
|
||||
// Watch for root changes
|
||||
err := h.dataSources.CARoots.Notify(ctx, &structs.DCSpecificRequest{
|
||||
Datacenter: h.source.Datacenter,
|
||||
QueryOptions: structs.QueryOptions{Token: h.token},
|
||||
Source: *h.source,
|
||||
}, rootsWatchID, h.ch)
|
||||
if err != nil {
|
||||
return snap, err
|
||||
}
|
||||
|
||||
// Get information about the entire service mesh.
|
||||
err = h.dataSources.ConfigEntry.Notify(ctx, &structs.ConfigEntryQuery{
|
||||
Kind: structs.MeshConfig,
|
||||
Name: structs.MeshConfigMesh,
|
||||
Datacenter: h.source.Datacenter,
|
||||
QueryOptions: structs.QueryOptions{Token: h.token},
|
||||
EnterpriseMeta: *structs.DefaultEnterpriseMetaInPartition(h.proxyID.PartitionOrDefault()),
|
||||
}, meshConfigEntryID, h.ch)
|
||||
if err != nil {
|
||||
return snap, err
|
||||
}
|
||||
|
||||
// Watch the api-gateway's config entry
|
||||
err = h.subscribeToConfigEntry(ctx, structs.APIGateway, h.service, gatewayConfigWatchID)
|
||||
if err != nil {
|
||||
return snap, err
|
||||
}
|
||||
|
||||
// Watch the bound-api-gateway's config entry
|
||||
err = h.subscribeToConfigEntry(ctx, structs.BoundAPIGateway, h.service, gatewayConfigWatchID)
|
||||
if err != nil {
|
||||
return snap, err
|
||||
}
|
||||
|
||||
snap.APIGateway.Listeners = make(map[string]structs.APIGatewayListener)
|
||||
snap.APIGateway.BoundListeners = make(map[string]structs.BoundAPIGatewayListener)
|
||||
snap.APIGateway.HTTPRoutes = watch.NewMap[structs.ResourceReference, *structs.HTTPRouteConfigEntry]()
|
||||
snap.APIGateway.TCPRoutes = watch.NewMap[structs.ResourceReference, *structs.TCPRouteConfigEntry]()
|
||||
snap.APIGateway.Certificates = watch.NewMap[structs.ResourceReference, *structs.InlineCertificateConfigEntry]()
|
||||
|
||||
// These need to be initialized here but are set by handlerUpstreams
|
||||
snap.APIGateway.DiscoveryChain = make(map[UpstreamID]*structs.CompiledDiscoveryChain)
|
||||
snap.APIGateway.PeerUpstreamEndpoints = watch.NewMap[UpstreamID, structs.CheckServiceNodes]()
|
||||
snap.APIGateway.PeerUpstreamEndpointsUseHostnames = make(map[UpstreamID]struct{})
|
||||
snap.APIGateway.UpstreamPeerTrustBundles = watch.NewMap[string, *pbpeering.PeeringTrustBundle]()
|
||||
snap.APIGateway.WatchedDiscoveryChains = make(map[UpstreamID]context.CancelFunc)
|
||||
snap.APIGateway.WatchedGateways = make(map[UpstreamID]map[string]context.CancelFunc)
|
||||
snap.APIGateway.WatchedGatewayEndpoints = make(map[UpstreamID]map[string]structs.CheckServiceNodes)
|
||||
snap.APIGateway.WatchedUpstreams = make(map[UpstreamID]map[string]context.CancelFunc)
|
||||
snap.APIGateway.WatchedUpstreamEndpoints = make(map[UpstreamID]map[string]structs.CheckServiceNodes)
|
||||
|
||||
return snap, nil
|
||||
}
|
||||
|
||||
func (h *handlerAPIGateway) subscribeToConfigEntry(ctx context.Context, kind, name, watchID string) error {
|
||||
return h.dataSources.ConfigEntry.Notify(ctx, &structs.ConfigEntryQuery{
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Datacenter: h.source.Datacenter,
|
||||
QueryOptions: structs.QueryOptions{Token: h.token},
|
||||
EnterpriseMeta: h.proxyID.EnterpriseMeta,
|
||||
}, watchID, h.ch)
|
||||
}
|
||||
|
||||
// handleUpdate responds to changes in the api-gateway. In general, we want
|
||||
// to crawl the various resources related to or attached to the gateway and
|
||||
// collect the list of things need to generate xDS. This list of resources
|
||||
// includes the bound-api-gateway, http-routes, tcp-routes, and inline-certificates.
|
||||
func (h *handlerAPIGateway) handleUpdate(ctx context.Context, u UpdateEvent, snap *ConfigSnapshot) error {
|
||||
if u.Err != nil {
|
||||
return fmt.Errorf("error filling agent cache: %v", u.Err)
|
||||
}
|
||||
|
||||
switch {
|
||||
case u.CorrelationID == rootsWatchID:
|
||||
// Handle change in the CA roots
|
||||
if err := h.handleRootCAUpdate(u, snap); err != nil {
|
||||
return err
|
||||
}
|
||||
case u.CorrelationID == gatewayConfigWatchID:
|
||||
// Handle change in the api-gateway or bound-api-gateway config entry
|
||||
if err := h.handleGatewayConfigUpdate(ctx, u, snap); err != nil {
|
||||
return err
|
||||
}
|
||||
case u.CorrelationID == inlineCertificateConfigWatchID:
|
||||
// Handle change in an attached inline-certificate config entry
|
||||
if err := h.handleInlineCertConfigUpdate(ctx, u, snap); err != nil {
|
||||
return err
|
||||
}
|
||||
case u.CorrelationID == routeConfigWatchID:
|
||||
// Handle change in an attached http-route or tcp-route config entry
|
||||
if err := h.handleRouteConfigUpdate(ctx, u, snap); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return (*handlerUpstreams)(h).handleUpdateUpstreams(ctx, u, snap)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// handleRootCAUpdate responds to changes in the watched root CA for a gateway
|
||||
func (h *handlerAPIGateway) handleRootCAUpdate(u UpdateEvent, snap *ConfigSnapshot) error {
|
||||
roots, ok := u.Result.(*structs.IndexedCARoots)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid type for response: %T", u.Result)
|
||||
}
|
||||
snap.Roots = roots
|
||||
return nil
|
||||
}
|
||||
|
||||
// handleGatewayConfigUpdate responds to changes in the watched config entry for a gateway.
|
||||
// In particular, we want to make sure that we're subscribing to any attached resources such
|
||||
// as routes and certificates. These additional subscriptions will enable us to update the
|
||||
// config snapshot appropriately for any route or certificate changes.
|
||||
func (h *handlerAPIGateway) handleGatewayConfigUpdate(ctx context.Context, u UpdateEvent, snap *ConfigSnapshot) error {
|
||||
resp, ok := u.Result.(*structs.ConfigEntryResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid type for response: %T", u.Result)
|
||||
} else if resp.Entry == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch gwConf := resp.Entry.(type) {
|
||||
case *structs.BoundAPIGatewayConfigEntry:
|
||||
snap.APIGateway.BoundGatewayConfig = gwConf
|
||||
|
||||
seenRefs := make(map[structs.ResourceReference]any)
|
||||
for _, listener := range gwConf.Listeners {
|
||||
snap.APIGateway.BoundListeners[listener.Name] = listener
|
||||
|
||||
// Subscribe to changes in each attached x-route config entry
|
||||
for _, ref := range listener.Routes {
|
||||
seenRefs[ref] = struct{}{}
|
||||
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
switch ref.Kind {
|
||||
case structs.HTTPRoute:
|
||||
snap.APIGateway.HTTPRoutes.InitWatch(ref, cancel)
|
||||
case structs.TCPRoute:
|
||||
snap.APIGateway.TCPRoutes.InitWatch(ref, cancel)
|
||||
default:
|
||||
cancel()
|
||||
return fmt.Errorf("unexpected route kind on gateway: %s", ref.Kind)
|
||||
}
|
||||
|
||||
err := h.subscribeToConfigEntry(ctx, ref.Kind, ref.Name, routeConfigWatchID)
|
||||
if err != nil {
|
||||
// TODO May want to continue
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Subscribe to changes in each attached inline-certificate config entry
|
||||
for _, ref := range listener.Certificates {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
seenRefs[ref] = struct{}{}
|
||||
snap.APIGateway.Certificates.InitWatch(ref, cancel)
|
||||
|
||||
err := h.subscribeToConfigEntry(ctx, ref.Kind, ref.Name, inlineCertificateConfigWatchID)
|
||||
if err != nil {
|
||||
// TODO May want to continue
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unsubscribe from any config entries that are no longer attached
|
||||
snap.APIGateway.HTTPRoutes.ForEachKey(func(ref structs.ResourceReference) bool {
|
||||
if _, ok := seenRefs[ref]; !ok {
|
||||
snap.APIGateway.HTTPRoutes.CancelWatch(ref)
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
snap.APIGateway.TCPRoutes.ForEachKey(func(ref structs.ResourceReference) bool {
|
||||
if _, ok := seenRefs[ref]; !ok {
|
||||
snap.APIGateway.TCPRoutes.CancelWatch(ref)
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
snap.APIGateway.Certificates.ForEachKey(func(ref structs.ResourceReference) bool {
|
||||
if _, ok := seenRefs[ref]; !ok {
|
||||
snap.APIGateway.Certificates.CancelWatch(ref)
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
snap.APIGateway.BoundGatewayConfigLoaded = true
|
||||
break
|
||||
case *structs.APIGatewayConfigEntry:
|
||||
snap.APIGateway.GatewayConfig = gwConf
|
||||
|
||||
for _, listener := range gwConf.Listeners {
|
||||
snap.APIGateway.Listeners[listener.Name] = listener
|
||||
}
|
||||
|
||||
snap.APIGateway.GatewayConfigLoaded = true
|
||||
break
|
||||
default:
|
||||
return fmt.Errorf("invalid type for config entry: %T", resp.Entry)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// handleInlineCertConfigUpdate stores the certificate for the gateway
|
||||
func (h *handlerAPIGateway) handleInlineCertConfigUpdate(_ context.Context, u UpdateEvent, snap *ConfigSnapshot) error {
|
||||
resp, ok := u.Result.(*structs.ConfigEntryResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid type for response: %T", u.Result)
|
||||
} else if resp.Entry == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
cfg, ok := resp.Entry.(*structs.InlineCertificateConfigEntry)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid type for config entry: %T", resp.Entry)
|
||||
}
|
||||
|
||||
// TODO Consider if unset SectionName and acl.EnterpriseMeta could trip us up
|
||||
ref := structs.ResourceReference{
|
||||
Kind: cfg.GetKind(),
|
||||
Name: cfg.GetName(),
|
||||
}
|
||||
|
||||
snap.APIGateway.Certificates.Set(ref, cfg)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// handleRouteConfigUpdate builds the list of upstreams for services on
|
||||
// the route and watches the related discovery chains.
|
||||
func (h *handlerAPIGateway) handleRouteConfigUpdate(ctx context.Context, u UpdateEvent, snap *ConfigSnapshot) error {
|
||||
resp, ok := u.Result.(*structs.ConfigEntryResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid type for response: %T", u.Result)
|
||||
} else if resp.Entry == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO Consider if unset SectionName and acl.EnterpriseMeta could trip us up
|
||||
ref := structs.ResourceReference{
|
||||
Kind: resp.Entry.GetKind(),
|
||||
Name: resp.Entry.GetName(),
|
||||
}
|
||||
|
||||
seenUpstreamIDs := make(map[UpstreamID]struct{})
|
||||
upstreams := make(map[APIGatewayListenerKey]structs.Upstreams)
|
||||
|
||||
switch route := resp.Entry.(type) {
|
||||
case *structs.HTTPRouteConfigEntry:
|
||||
snap.APIGateway.HTTPRoutes.Set(ref, route)
|
||||
|
||||
for _, rule := range route.Rules {
|
||||
for _, service := range rule.Services {
|
||||
for _, listener := range snap.APIGateway.Listeners {
|
||||
shouldBind := false
|
||||
for _, parent := range route.Parents {
|
||||
if h.referenceIsForListener(parent, listener, snap) {
|
||||
shouldBind = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !shouldBind {
|
||||
continue
|
||||
}
|
||||
|
||||
upstream := structs.Upstream{
|
||||
DestinationName: service.Name,
|
||||
DestinationNamespace: service.NamespaceOrDefault(),
|
||||
DestinationPartition: service.PartitionOrDefault(),
|
||||
LocalBindPort: listener.Port,
|
||||
// TODO IngressHosts: g.Hosts,
|
||||
// Pass the protocol that was configured on the listener in order
|
||||
// to force that protocol on the Envoy listener.
|
||||
Config: map[string]interface{}{
|
||||
"protocol": "http",
|
||||
},
|
||||
}
|
||||
|
||||
listenerKey := APIGatewayListenerKey{Protocol: string(listener.Protocol), Port: listener.Port}
|
||||
upstreams[listenerKey] = append(upstreams[listenerKey], upstream)
|
||||
}
|
||||
|
||||
upstreamID := NewUpstreamIDFromServiceName(service.ServiceName())
|
||||
seenUpstreamIDs[upstreamID] = struct{}{}
|
||||
|
||||
watchOpts := discoveryChainWatchOpts{
|
||||
id: upstreamID,
|
||||
name: service.Name,
|
||||
namespace: service.NamespaceOrDefault(),
|
||||
partition: service.PartitionOrDefault(),
|
||||
datacenter: h.stateConfig.source.Datacenter,
|
||||
}
|
||||
|
||||
handler := &handlerUpstreams{handlerState: h.handlerState}
|
||||
if err := handler.watchDiscoveryChain(ctx, snap, watchOpts); err != nil {
|
||||
return fmt.Errorf("failed to watch discovery chain for %s: %w", upstreamID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case *structs.TCPRouteConfigEntry:
|
||||
snap.APIGateway.TCPRoutes.Set(ref, route)
|
||||
|
||||
for _, service := range route.Services {
|
||||
upstreamID := NewUpstreamIDFromServiceName(service.ServiceName())
|
||||
seenUpstreamIDs[upstreamID] = struct{}{}
|
||||
|
||||
// For each listener, check if this route should bind and, if so, create an upstream.
|
||||
for _, listener := range snap.APIGateway.Listeners {
|
||||
shouldBind := false
|
||||
for _, parent := range route.Parents {
|
||||
if h.referenceIsForListener(parent, listener, snap) {
|
||||
shouldBind = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !shouldBind {
|
||||
continue
|
||||
}
|
||||
|
||||
upstream := structs.Upstream{
|
||||
DestinationName: service.Name,
|
||||
DestinationNamespace: service.NamespaceOrDefault(),
|
||||
DestinationPartition: service.PartitionOrDefault(),
|
||||
LocalBindPort: listener.Port,
|
||||
//IngressHosts: g.Hosts,
|
||||
// Pass the protocol that was configured on the ingress listener in order
|
||||
// to force that protocol on the Envoy listener.
|
||||
Config: map[string]interface{}{
|
||||
"protocol": "tcp",
|
||||
},
|
||||
}
|
||||
|
||||
listenerKey := APIGatewayListenerKey{Protocol: string(listener.Protocol), Port: listener.Port}
|
||||
upstreams[listenerKey] = append(upstreams[listenerKey], upstream)
|
||||
}
|
||||
|
||||
watchOpts := discoveryChainWatchOpts{
|
||||
id: upstreamID,
|
||||
name: service.Name,
|
||||
namespace: service.NamespaceOrDefault(),
|
||||
partition: service.PartitionOrDefault(),
|
||||
datacenter: h.stateConfig.source.Datacenter,
|
||||
}
|
||||
|
||||
handler := &handlerUpstreams{handlerState: h.handlerState}
|
||||
if err := handler.watchDiscoveryChain(ctx, snap, watchOpts); err != nil {
|
||||
return fmt.Errorf("failed to watch discovery chain for %s: %w", upstreamID, err)
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("invalid type for config entry: %T", resp.Entry)
|
||||
}
|
||||
|
||||
snap.APIGateway.Upstreams = upstreams
|
||||
snap.APIGateway.UpstreamsSet = seenUpstreamIDs
|
||||
//snap.APIGateway.Hosts = TODO
|
||||
snap.APIGateway.AreHostsSet = true
|
||||
|
||||
// Stop watching any upstreams and discovery chains that have become irrelevant
|
||||
for upstreamID, cancelDiscoChain := range snap.APIGateway.WatchedDiscoveryChains {
|
||||
if _, ok := seenUpstreamIDs[upstreamID]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
for targetID, cancelUpstream := range snap.APIGateway.WatchedUpstreams[upstreamID] {
|
||||
cancelUpstream()
|
||||
delete(snap.APIGateway.WatchedUpstreams[upstreamID], targetID)
|
||||
delete(snap.APIGateway.WatchedUpstreamEndpoints[upstreamID], targetID)
|
||||
|
||||
if targetUID := NewUpstreamIDFromTargetID(targetID); targetUID.Peer != "" {
|
||||
snap.APIGateway.PeerUpstreamEndpoints.CancelWatch(targetUID)
|
||||
snap.APIGateway.UpstreamPeerTrustBundles.CancelWatch(targetUID.Peer)
|
||||
}
|
||||
}
|
||||
|
||||
cancelDiscoChain()
|
||||
delete(snap.APIGateway.WatchedDiscoveryChains, upstreamID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// referenceIsForListener returns whether the provided structs.ResourceReference
|
||||
// targets the provided structs.APIGatewayListener. For this to be true, the kind
|
||||
// and name must match the structs.APIGatewayConfigEntry containing the listener,
|
||||
// and the reference must specify either no section name or the name of the listener
|
||||
// as the section name.
|
||||
//
|
||||
// TODO This would probably be more generally useful as a helper in the structs pkg
|
||||
func (h *handlerAPIGateway) referenceIsForListener(ref structs.ResourceReference, listener structs.APIGatewayListener, snap *ConfigSnapshot) bool {
|
||||
if ref.Kind != snap.APIGateway.GatewayConfig.Kind {
|
||||
return false
|
||||
}
|
||||
if ref.Name != snap.APIGateway.GatewayConfig.Name {
|
||||
return false
|
||||
}
|
||||
return ref.SectionName == "" || ref.SectionName == listener.Name
|
||||
}
|
|
@ -10,6 +10,7 @@ deep-copy -pointer-receiver \
|
|||
-type ConfigSnapshotUpstreams \
|
||||
-type PeerServersValue \
|
||||
-type PeeringServiceValue \
|
||||
-type configSnapshotAPIGateway \
|
||||
-type configSnapshotConnectProxy \
|
||||
-type configSnapshotIngressGateway \
|
||||
-type configSnapshotMeshGateway \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// generated by deep-copy -pointer-receiver -o ./proxycfg.deepcopy.go -type ConfigSnapshot -type ConfigSnapshotUpstreams -type PeerServersValue -type PeeringServiceValue -type configSnapshotConnectProxy -type configSnapshotIngressGateway -type configSnapshotMeshGateway -type configSnapshotTerminatingGateway ./; DO NOT EDIT.
|
||||
// generated by deep-copy -pointer-receiver -o ./proxycfg.deepcopy.go -type ConfigSnapshot -type ConfigSnapshotUpstreams -type PeerServersValue -type PeeringServiceValue -type configSnapshotAPIGateway -type configSnapshotConnectProxy -type configSnapshotIngressGateway -type configSnapshotMeshGateway -type configSnapshotTerminatingGateway ./; DO NOT EDIT.
|
||||
|
||||
package proxycfg
|
||||
|
||||
|
@ -47,6 +47,10 @@ func (o *ConfigSnapshot) DeepCopy() *ConfigSnapshot {
|
|||
retV := o.IngressGateway.DeepCopy()
|
||||
cp.IngressGateway = *retV
|
||||
}
|
||||
{
|
||||
retV := o.APIGateway.DeepCopy()
|
||||
cp.APIGateway = *retV
|
||||
}
|
||||
return &cp
|
||||
}
|
||||
|
||||
|
@ -209,6 +213,103 @@ func (o *PeeringServiceValue) DeepCopy() *PeeringServiceValue {
|
|||
return &cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of *configSnapshotAPIGateway
|
||||
func (o *configSnapshotAPIGateway) DeepCopy() *configSnapshotAPIGateway {
|
||||
var cp configSnapshotAPIGateway = *o
|
||||
{
|
||||
retV := o.ConfigSnapshotUpstreams.DeepCopy()
|
||||
cp.ConfigSnapshotUpstreams = *retV
|
||||
}
|
||||
if o.TLSConfig.SDS != nil {
|
||||
cp.TLSConfig.SDS = new(structs.GatewayTLSSDSConfig)
|
||||
*cp.TLSConfig.SDS = *o.TLSConfig.SDS
|
||||
}
|
||||
if o.TLSConfig.CipherSuites != nil {
|
||||
cp.TLSConfig.CipherSuites = make([]types.TLSCipherSuite, len(o.TLSConfig.CipherSuites))
|
||||
copy(cp.TLSConfig.CipherSuites, o.TLSConfig.CipherSuites)
|
||||
}
|
||||
if o.GatewayConfig != nil {
|
||||
cp.GatewayConfig = new(structs.APIGatewayConfigEntry)
|
||||
*cp.GatewayConfig = *o.GatewayConfig
|
||||
if o.GatewayConfig.Listeners != nil {
|
||||
cp.GatewayConfig.Listeners = make([]structs.APIGatewayListener, len(o.GatewayConfig.Listeners))
|
||||
copy(cp.GatewayConfig.Listeners, o.GatewayConfig.Listeners)
|
||||
for i4 := range o.GatewayConfig.Listeners {
|
||||
{
|
||||
retV := o.GatewayConfig.Listeners[i4].DeepCopy()
|
||||
cp.GatewayConfig.Listeners[i4] = *retV
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
retV := o.GatewayConfig.Status.DeepCopy()
|
||||
cp.GatewayConfig.Status = *retV
|
||||
}
|
||||
if o.GatewayConfig.Meta != nil {
|
||||
cp.GatewayConfig.Meta = make(map[string]string, len(o.GatewayConfig.Meta))
|
||||
for k4, v4 := range o.GatewayConfig.Meta {
|
||||
cp.GatewayConfig.Meta[k4] = v4
|
||||
}
|
||||
}
|
||||
}
|
||||
if o.BoundGatewayConfig != nil {
|
||||
cp.BoundGatewayConfig = o.BoundGatewayConfig.DeepCopy()
|
||||
}
|
||||
if o.Hosts != nil {
|
||||
cp.Hosts = make([]string, len(o.Hosts))
|
||||
copy(cp.Hosts, o.Hosts)
|
||||
}
|
||||
if o.Upstreams != nil {
|
||||
cp.Upstreams = make(map[IngressListenerKey]structs.Upstreams, len(o.Upstreams))
|
||||
for k2, v2 := range o.Upstreams {
|
||||
var cp_Upstreams_v2 structs.Upstreams
|
||||
if v2 != nil {
|
||||
cp_Upstreams_v2 = make([]structs.Upstream, len(v2))
|
||||
copy(cp_Upstreams_v2, v2)
|
||||
for i3 := range v2 {
|
||||
{
|
||||
retV := v2[i3].DeepCopy()
|
||||
cp_Upstreams_v2[i3] = *retV
|
||||
}
|
||||
}
|
||||
}
|
||||
cp.Upstreams[k2] = cp_Upstreams_v2
|
||||
}
|
||||
}
|
||||
if o.UpstreamsSet != nil {
|
||||
cp.UpstreamsSet = make(map[UpstreamID]struct{}, len(o.UpstreamsSet))
|
||||
for k2, v2 := range o.UpstreamsSet {
|
||||
cp.UpstreamsSet[k2] = v2
|
||||
}
|
||||
}
|
||||
cp.HTTPRoutes = o.HTTPRoutes.DeepCopy()
|
||||
cp.TCPRoutes = o.TCPRoutes.DeepCopy()
|
||||
cp.Certificates = o.Certificates.DeepCopy()
|
||||
if o.Listeners != nil {
|
||||
cp.Listeners = make(map[string]structs.APIGatewayListener, len(o.Listeners))
|
||||
for k2, v2 := range o.Listeners {
|
||||
var cp_Listeners_v2 structs.APIGatewayListener
|
||||
{
|
||||
retV := v2.DeepCopy()
|
||||
cp_Listeners_v2 = *retV
|
||||
}
|
||||
cp.Listeners[k2] = cp_Listeners_v2
|
||||
}
|
||||
}
|
||||
if o.BoundListeners != nil {
|
||||
cp.BoundListeners = make(map[string]structs.BoundAPIGatewayListener, len(o.BoundListeners))
|
||||
for k2, v2 := range o.BoundListeners {
|
||||
var cp_BoundListeners_v2 structs.BoundAPIGatewayListener
|
||||
{
|
||||
retV := v2.DeepCopy()
|
||||
cp_BoundListeners_v2 = *retV
|
||||
}
|
||||
cp.BoundListeners[k2] = cp_BoundListeners_v2
|
||||
}
|
||||
}
|
||||
return &cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of *configSnapshotConnectProxy
|
||||
func (o *configSnapshotConnectProxy) DeepCopy() *configSnapshotConnectProxy {
|
||||
var cp configSnapshotConnectProxy = *o
|
||||
|
|
|
@ -639,6 +639,65 @@ func (c *configSnapshotMeshGateway) isEmptyPeering() bool {
|
|||
!c.PeeringTrustBundlesSet
|
||||
}
|
||||
|
||||
type configSnapshotAPIGateway struct {
|
||||
ConfigSnapshotUpstreams
|
||||
|
||||
TLSConfig structs.GatewayTLSConfig
|
||||
|
||||
// GatewayConfigLoaded is used to determine if we have received the initial
|
||||
// api-gateway config entry yet.
|
||||
GatewayConfigLoaded bool
|
||||
GatewayConfig *structs.APIGatewayConfigEntry
|
||||
|
||||
// BoundGatewayConfigLoaded is used to determine if we have received the initial
|
||||
// bound-api-gateway config entry yet.
|
||||
BoundGatewayConfigLoaded bool
|
||||
BoundGatewayConfig *structs.BoundAPIGatewayConfigEntry
|
||||
|
||||
// Hosts is the list of extra host entries to add to our leaf cert's DNS SANs
|
||||
Hosts []string
|
||||
AreHostsSet bool
|
||||
|
||||
// LeafCertWatchCancel is a CancelFunc to use when refreshing this gateway's
|
||||
// leaf cert watch with different parameters.
|
||||
//LeafCertWatchCancel context.CancelFunc
|
||||
|
||||
// Upstreams is a list of upstreams this ingress gateway should serve traffic
|
||||
// to. This is constructed from the ingress-gateway config entry, and uses
|
||||
// the GatewayServices RPC to retrieve them.
|
||||
// TODO Determine if this is updated "for free" or not. If not, we might need
|
||||
// to do some work to populate it in handlerAPIGateway
|
||||
Upstreams map[IngressListenerKey]structs.Upstreams
|
||||
|
||||
// UpstreamsSet is the unique set of UpstreamID the gateway routes to.
|
||||
UpstreamsSet map[UpstreamID]struct{}
|
||||
|
||||
HTTPRoutes watch.Map[structs.ResourceReference, *structs.HTTPRouteConfigEntry]
|
||||
TCPRoutes watch.Map[structs.ResourceReference, *structs.TCPRouteConfigEntry]
|
||||
Certificates watch.Map[structs.ResourceReference, *structs.InlineCertificateConfigEntry]
|
||||
|
||||
// Listeners is the original listener config from the api-gateway config
|
||||
// entry to save us trying to pass fields through Upstreams
|
||||
Listeners map[string]structs.APIGatewayListener
|
||||
|
||||
BoundListeners map[string]structs.BoundAPIGatewayListener
|
||||
}
|
||||
|
||||
// ToIngress converts a configSnapshotAPIGateway to a configSnapshotIngressGateway.
|
||||
// This is temporary, for the sake of re-using existing codepaths when integrating
|
||||
// Consul API Gateway into Consul core.
|
||||
//
|
||||
// FUTURE: Remove when API gateways have custom snapshot generation
|
||||
func (c *configSnapshotAPIGateway) ToIngress() configSnapshotIngressGateway {
|
||||
|
||||
return configSnapshotIngressGateway{
|
||||
ConfigSnapshotUpstreams: c.ConfigSnapshotUpstreams,
|
||||
// TODO Build from c.Listeners
|
||||
// Listeners:
|
||||
Defaults: structs.IngressServiceConfig{},
|
||||
}
|
||||
}
|
||||
|
||||
type configSnapshotIngressGateway struct {
|
||||
ConfigSnapshotUpstreams
|
||||
|
||||
|
@ -687,6 +746,8 @@ func (c *configSnapshotIngressGateway) isEmpty() bool {
|
|||
!c.MeshConfigSet
|
||||
}
|
||||
|
||||
type APIGatewayListenerKey = IngressListenerKey
|
||||
|
||||
type IngressListenerKey struct {
|
||||
Protocol string
|
||||
Port int
|
||||
|
@ -734,6 +795,9 @@ type ConfigSnapshot struct {
|
|||
|
||||
// ingress-gateway specific
|
||||
IngressGateway configSnapshotIngressGateway
|
||||
|
||||
// api-gateway specific
|
||||
APIGateway configSnapshotAPIGateway
|
||||
}
|
||||
|
||||
// Valid returns whether or not the snapshot has all required fields filled yet.
|
||||
|
@ -773,6 +837,14 @@ func (s *ConfigSnapshot) Valid() bool {
|
|||
s.IngressGateway.GatewayConfigLoaded &&
|
||||
s.IngressGateway.HostsSet &&
|
||||
s.IngressGateway.MeshConfigSet
|
||||
|
||||
case structs.ServiceKindAPIGateway:
|
||||
// TODO Is this the proper set of things to validate?
|
||||
return s.Roots != nil &&
|
||||
s.APIGateway.GatewayConfigLoaded &&
|
||||
s.APIGateway.BoundGatewayConfigLoaded &&
|
||||
s.APIGateway.AreHostsSet &&
|
||||
s.APIGateway.MeshConfigSet
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
@ -806,6 +878,15 @@ func (s *ConfigSnapshot) Clone() *ConfigSnapshot {
|
|||
snap.IngressGateway.WatchedDiscoveryChains = nil
|
||||
// only ingress-gateway
|
||||
snap.IngressGateway.LeafCertWatchCancel = nil
|
||||
case structs.ServiceKindAPIGateway:
|
||||
// common with connect-proxy and api-gateway
|
||||
snap.APIGateway.WatchedUpstreams = nil
|
||||
snap.APIGateway.WatchedGateways = nil
|
||||
snap.APIGateway.WatchedDiscoveryChains = nil
|
||||
|
||||
// only api-gateway
|
||||
//snap.APIGateway.LeafCertWatchCancel = nil
|
||||
//snap.APIGateway.
|
||||
}
|
||||
|
||||
return snap
|
||||
|
@ -817,6 +898,8 @@ func (s *ConfigSnapshot) Leaf() *structs.IssuedCert {
|
|||
return s.ConnectProxy.Leaf
|
||||
case structs.ServiceKindIngressGateway:
|
||||
return s.IngressGateway.Leaf
|
||||
case structs.ServiceKindAPIGateway:
|
||||
return s.APIGateway.Leaf
|
||||
case structs.ServiceKindMeshGateway:
|
||||
return s.MeshGateway.Leaf
|
||||
default:
|
||||
|
@ -850,6 +933,8 @@ func (s *ConfigSnapshot) MeshConfig() *structs.MeshConfigEntry {
|
|||
return s.ConnectProxy.MeshConfig
|
||||
case structs.ServiceKindIngressGateway:
|
||||
return s.IngressGateway.MeshConfig
|
||||
case structs.ServiceKindAPIGateway:
|
||||
return s.APIGateway.MeshConfig
|
||||
case structs.ServiceKindTerminatingGateway:
|
||||
return s.TerminatingGateway.MeshConfig
|
||||
case structs.ServiceKindMeshGateway:
|
||||
|
@ -881,6 +966,8 @@ func (s *ConfigSnapshot) ToConfigSnapshotUpstreams() (*ConfigSnapshotUpstreams,
|
|||
return &s.ConnectProxy.ConfigSnapshotUpstreams, nil
|
||||
case structs.ServiceKindIngressGateway:
|
||||
return &s.IngressGateway.ConfigSnapshotUpstreams, nil
|
||||
case structs.ServiceKindAPIGateway:
|
||||
return &s.APIGateway.ConfigSnapshotUpstreams, nil
|
||||
default:
|
||||
// This is a coherence check and should never fail
|
||||
return nil, fmt.Errorf("No upstream snapshot for gateway mode %q", s.Kind)
|
||||
|
|
|
@ -32,6 +32,8 @@ const (
|
|||
serviceResolversWatchID = "service-resolvers"
|
||||
gatewayServicesWatchID = "gateway-services"
|
||||
gatewayConfigWatchID = "gateway-config"
|
||||
inlineCertificateConfigWatchID = "inline-certificate-config"
|
||||
routeConfigWatchID = "route-config"
|
||||
externalServiceIDPrefix = "external-service:"
|
||||
serviceLeafIDPrefix = "service-leaf:"
|
||||
serviceConfigIDPrefix = "service-config:"
|
||||
|
@ -198,6 +200,8 @@ func newKindHandler(config stateConfig, s serviceInstance, ch chan UpdateEvent)
|
|||
handler = &handlerMeshGateway{handlerState: h}
|
||||
case structs.ServiceKindIngressGateway:
|
||||
handler = &handlerIngressGateway{handlerState: h}
|
||||
case structs.ServiceKindAPIGateway:
|
||||
handler = &handlerAPIGateway{handlerState: h}
|
||||
default:
|
||||
return nil, errors.New("not a connect-proxy, terminating-gateway, mesh-gateway, or ingress-gateway")
|
||||
}
|
||||
|
|
|
@ -63,6 +63,14 @@ func (s *handlerUpstreams) handleUpdateUpstreams(ctx context.Context, u UpdateEv
|
|||
uid := UpstreamIDFromString(uidString)
|
||||
|
||||
switch snap.Kind {
|
||||
case structs.ServiceKindAPIGateway:
|
||||
if _, ok := snap.APIGateway.UpstreamsSet[uid]; !ok {
|
||||
// Discovery chain is not associated with a known explicit or implicit upstream so it is purged/skipped.
|
||||
// The associated watch was likely cancelled.
|
||||
delete(upstreamsSnapshot.DiscoveryChain, uid)
|
||||
s.logger.Trace("discovery-chain watch fired for unknown upstream", "upstream", uid)
|
||||
return nil
|
||||
}
|
||||
case structs.ServiceKindIngressGateway:
|
||||
if _, ok := snap.IngressGateway.UpstreamsSet[uid]; !ok {
|
||||
// Discovery chain is not associated with a known explicit or implicit upstream so it is purged/skipped.
|
||||
|
@ -533,6 +541,8 @@ type discoveryChainWatchOpts struct {
|
|||
func (s *handlerUpstreams) watchDiscoveryChain(ctx context.Context, snap *ConfigSnapshot, opts discoveryChainWatchOpts) error {
|
||||
var watchedDiscoveryChains map[UpstreamID]context.CancelFunc
|
||||
switch s.kind {
|
||||
case structs.ServiceKindAPIGateway:
|
||||
watchedDiscoveryChains = snap.APIGateway.WatchedDiscoveryChains
|
||||
case structs.ServiceKindIngressGateway:
|
||||
watchedDiscoveryChains = snap.IngressGateway.WatchedDiscoveryChains
|
||||
case structs.ServiceKindConnectProxy:
|
||||
|
|
|
@ -704,6 +704,7 @@ type APIGatewayConfigEntry struct {
|
|||
// Listeners is the set of listener configuration to which an API Gateway
|
||||
// might bind.
|
||||
Listeners []APIGatewayListener
|
||||
|
||||
// Status is the asynchronous status which an APIGateway propagates to the user.
|
||||
Status Status
|
||||
|
||||
|
@ -862,16 +863,16 @@ const (
|
|||
// APIGatewayListener represents an individual listener for an APIGateway
|
||||
type APIGatewayListener struct {
|
||||
// Name is the optional name of the listener in a given gateway. This is
|
||||
// optional, however, it must be unique. Therefore, if a gateway has more
|
||||
// than a single listener, all but one must specify a Name.
|
||||
// optional but must be unique within a gateway; therefore, if a gateway
|
||||
// has more than a single listener, all but one must specify a Name.
|
||||
Name string
|
||||
// Hostname is the host name that a listener should be bound to, if
|
||||
// Hostname is the host name that a listener should be bound to. If
|
||||
// unspecified, the listener accepts requests for all hostnames.
|
||||
Hostname string
|
||||
// Port is the port at which this listener should bind.
|
||||
Port int
|
||||
// Protocol is the protocol that a listener should use, it must
|
||||
// either be http or tcp
|
||||
// Protocol is the protocol that a listener should use. It must
|
||||
// either be http or tcp.
|
||||
Protocol APIGatewayListenerProtocol
|
||||
// TLS is the TLS settings for the listener.
|
||||
TLS APIGatewayTLSConfiguration
|
||||
|
|
|
@ -244,6 +244,10 @@ type HTTPService struct {
|
|||
acl.EnterpriseMeta
|
||||
}
|
||||
|
||||
func (s HTTPService) ServiceName() ServiceName {
|
||||
return NewServiceName(s.Name, &s.EnterpriseMeta)
|
||||
}
|
||||
|
||||
var _ ControlledConfigEntry = (*HTTPRouteConfigEntry)(nil)
|
||||
|
||||
func (e *HTTPRouteConfigEntry) GetStatus() Status {
|
||||
|
@ -398,3 +402,7 @@ type TCPService struct {
|
|||
|
||||
acl.EnterpriseMeta
|
||||
}
|
||||
|
||||
func (s TCPService) ServiceName() ServiceName {
|
||||
return NewServiceName(s.Name, &s.EnterpriseMeta)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ cd $PACKAGE_DIR
|
|||
deep-copy \
|
||||
-pointer-receiver \
|
||||
-o ./structs.deepcopy.go \
|
||||
-type APIGatewayListener \
|
||||
-type BoundAPIGatewayListener \
|
||||
-type CARoot \
|
||||
-type CheckServiceNode \
|
||||
-type CheckType \
|
||||
|
@ -21,10 +23,12 @@ deep-copy \
|
|||
-type GatewayService \
|
||||
-type GatewayServiceTLSConfig \
|
||||
-type HTTPHeaderModifiers \
|
||||
-type HTTPRouteConfigEntry \
|
||||
-type HashPolicy \
|
||||
-type HealthCheck \
|
||||
-type IndexedCARoots \
|
||||
-type IngressListener \
|
||||
-type InlineCertificateConfigEntry \
|
||||
-type Intention \
|
||||
-type IntentionPermission \
|
||||
-type LoadBalancer \
|
||||
|
@ -43,6 +47,7 @@ deep-copy \
|
|||
-type ServiceRoute \
|
||||
-type ServiceRouteDestination \
|
||||
-type ServiceRouteMatch \
|
||||
-type TCPRouteConfigEntry \
|
||||
-type Upstream \
|
||||
-type UpstreamConfiguration \
|
||||
-type Status \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// generated by deep-copy -pointer-receiver -o ./structs.deepcopy.go -type CARoot -type CheckServiceNode -type CheckType -type CompiledDiscoveryChain -type ConnectProxyConfig -type DiscoveryFailover -type DiscoveryGraphNode -type DiscoveryResolver -type DiscoveryRoute -type DiscoverySplit -type ExposeConfig -type GatewayService -type GatewayServiceTLSConfig -type HTTPHeaderModifiers -type HashPolicy -type HealthCheck -type IndexedCARoots -type IngressListener -type Intention -type IntentionPermission -type LoadBalancer -type MeshConfigEntry -type MeshDirectionalTLSConfig -type MeshTLSConfig -type Node -type NodeService -type PeeringServiceMeta -type ServiceConfigEntry -type ServiceConfigResponse -type ServiceConnect -type ServiceDefinition -type ServiceResolverConfigEntry -type ServiceResolverFailover -type ServiceRoute -type ServiceRouteDestination -type ServiceRouteMatch -type Upstream -type UpstreamConfiguration -type Status -type BoundAPIGatewayConfigEntry ./; DO NOT EDIT.
|
||||
// generated by deep-copy -pointer-receiver -o ./structs.deepcopy.go -type APIGatewayListener -type BoundAPIGatewayListener -type CARoot -type CheckServiceNode -type CheckType -type CompiledDiscoveryChain -type ConnectProxyConfig -type DiscoveryFailover -type DiscoveryGraphNode -type DiscoveryResolver -type DiscoveryRoute -type DiscoverySplit -type ExposeConfig -type GatewayService -type GatewayServiceTLSConfig -type HTTPHeaderModifiers -type HTTPRouteConfigEntry -type HashPolicy -type HealthCheck -type IndexedCARoots -type IngressListener -type InlineCertificateConfigEntry -type Intention -type IntentionPermission -type LoadBalancer -type MeshConfigEntry -type MeshDirectionalTLSConfig -type MeshTLSConfig -type Node -type NodeService -type PeeringServiceMeta -type ServiceConfigEntry -type ServiceConfigResponse -type ServiceConnect -type ServiceDefinition -type ServiceResolverConfigEntry -type ServiceResolverFailover -type ServiceRoute -type ServiceRouteDestination -type ServiceRouteMatch -type TCPRouteConfigEntry -type Upstream -type UpstreamConfiguration -type Status -type BoundAPIGatewayConfigEntry ./; DO NOT EDIT.
|
||||
|
||||
package structs
|
||||
|
||||
|
@ -7,6 +7,34 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// DeepCopy generates a deep copy of *APIGatewayListener
|
||||
func (o *APIGatewayListener) DeepCopy() *APIGatewayListener {
|
||||
var cp APIGatewayListener = *o
|
||||
if o.TLS.Certificates != nil {
|
||||
cp.TLS.Certificates = make([]ResourceReference, len(o.TLS.Certificates))
|
||||
copy(cp.TLS.Certificates, o.TLS.Certificates)
|
||||
}
|
||||
if o.TLS.CipherSuites != nil {
|
||||
cp.TLS.CipherSuites = make([]types.TLSCipherSuite, len(o.TLS.CipherSuites))
|
||||
copy(cp.TLS.CipherSuites, o.TLS.CipherSuites)
|
||||
}
|
||||
return &cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of *BoundAPIGatewayListener
|
||||
func (o *BoundAPIGatewayListener) DeepCopy() *BoundAPIGatewayListener {
|
||||
var cp BoundAPIGatewayListener = *o
|
||||
if o.Routes != nil {
|
||||
cp.Routes = make([]ResourceReference, len(o.Routes))
|
||||
copy(cp.Routes, o.Routes)
|
||||
}
|
||||
if o.Certificates != nil {
|
||||
cp.Certificates = make([]ResourceReference, len(o.Certificates))
|
||||
copy(cp.Certificates, o.Certificates)
|
||||
}
|
||||
return &cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of *CARoot
|
||||
func (o *CARoot) DeepCopy() *CARoot {
|
||||
var cp CARoot = *o
|
||||
|
@ -268,6 +296,100 @@ func (o *HTTPHeaderModifiers) DeepCopy() *HTTPHeaderModifiers {
|
|||
return &cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of *HTTPRouteConfigEntry
|
||||
func (o *HTTPRouteConfigEntry) DeepCopy() *HTTPRouteConfigEntry {
|
||||
var cp HTTPRouteConfigEntry = *o
|
||||
if o.Parents != nil {
|
||||
cp.Parents = make([]ResourceReference, len(o.Parents))
|
||||
copy(cp.Parents, o.Parents)
|
||||
}
|
||||
if o.Rules != nil {
|
||||
cp.Rules = make([]HTTPRouteRule, len(o.Rules))
|
||||
copy(cp.Rules, o.Rules)
|
||||
for i2 := range o.Rules {
|
||||
if o.Rules[i2].Filters.Headers != nil {
|
||||
cp.Rules[i2].Filters.Headers = make([]HTTPHeaderFilter, len(o.Rules[i2].Filters.Headers))
|
||||
copy(cp.Rules[i2].Filters.Headers, o.Rules[i2].Filters.Headers)
|
||||
for i5 := range o.Rules[i2].Filters.Headers {
|
||||
if o.Rules[i2].Filters.Headers[i5].Add != nil {
|
||||
cp.Rules[i2].Filters.Headers[i5].Add = make(map[string]string, len(o.Rules[i2].Filters.Headers[i5].Add))
|
||||
for k7, v7 := range o.Rules[i2].Filters.Headers[i5].Add {
|
||||
cp.Rules[i2].Filters.Headers[i5].Add[k7] = v7
|
||||
}
|
||||
}
|
||||
if o.Rules[i2].Filters.Headers[i5].Remove != nil {
|
||||
cp.Rules[i2].Filters.Headers[i5].Remove = make([]string, len(o.Rules[i2].Filters.Headers[i5].Remove))
|
||||
copy(cp.Rules[i2].Filters.Headers[i5].Remove, o.Rules[i2].Filters.Headers[i5].Remove)
|
||||
}
|
||||
if o.Rules[i2].Filters.Headers[i5].Set != nil {
|
||||
cp.Rules[i2].Filters.Headers[i5].Set = make(map[string]string, len(o.Rules[i2].Filters.Headers[i5].Set))
|
||||
for k7, v7 := range o.Rules[i2].Filters.Headers[i5].Set {
|
||||
cp.Rules[i2].Filters.Headers[i5].Set[k7] = v7
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if o.Rules[i2].Matches != nil {
|
||||
cp.Rules[i2].Matches = make([]HTTPMatch, len(o.Rules[i2].Matches))
|
||||
copy(cp.Rules[i2].Matches, o.Rules[i2].Matches)
|
||||
for i4 := range o.Rules[i2].Matches {
|
||||
if o.Rules[i2].Matches[i4].Headers != nil {
|
||||
cp.Rules[i2].Matches[i4].Headers = make([]HTTPHeaderMatch, len(o.Rules[i2].Matches[i4].Headers))
|
||||
copy(cp.Rules[i2].Matches[i4].Headers, o.Rules[i2].Matches[i4].Headers)
|
||||
}
|
||||
if o.Rules[i2].Matches[i4].Query != nil {
|
||||
cp.Rules[i2].Matches[i4].Query = make([]HTTPQueryMatch, len(o.Rules[i2].Matches[i4].Query))
|
||||
copy(cp.Rules[i2].Matches[i4].Query, o.Rules[i2].Matches[i4].Query)
|
||||
}
|
||||
}
|
||||
}
|
||||
if o.Rules[i2].Services != nil {
|
||||
cp.Rules[i2].Services = make([]HTTPService, len(o.Rules[i2].Services))
|
||||
copy(cp.Rules[i2].Services, o.Rules[i2].Services)
|
||||
for i4 := range o.Rules[i2].Services {
|
||||
if o.Rules[i2].Services[i4].Filters.Headers != nil {
|
||||
cp.Rules[i2].Services[i4].Filters.Headers = make([]HTTPHeaderFilter, len(o.Rules[i2].Services[i4].Filters.Headers))
|
||||
copy(cp.Rules[i2].Services[i4].Filters.Headers, o.Rules[i2].Services[i4].Filters.Headers)
|
||||
for i7 := range o.Rules[i2].Services[i4].Filters.Headers {
|
||||
if o.Rules[i2].Services[i4].Filters.Headers[i7].Add != nil {
|
||||
cp.Rules[i2].Services[i4].Filters.Headers[i7].Add = make(map[string]string, len(o.Rules[i2].Services[i4].Filters.Headers[i7].Add))
|
||||
for k9, v9 := range o.Rules[i2].Services[i4].Filters.Headers[i7].Add {
|
||||
cp.Rules[i2].Services[i4].Filters.Headers[i7].Add[k9] = v9
|
||||
}
|
||||
}
|
||||
if o.Rules[i2].Services[i4].Filters.Headers[i7].Remove != nil {
|
||||
cp.Rules[i2].Services[i4].Filters.Headers[i7].Remove = make([]string, len(o.Rules[i2].Services[i4].Filters.Headers[i7].Remove))
|
||||
copy(cp.Rules[i2].Services[i4].Filters.Headers[i7].Remove, o.Rules[i2].Services[i4].Filters.Headers[i7].Remove)
|
||||
}
|
||||
if o.Rules[i2].Services[i4].Filters.Headers[i7].Set != nil {
|
||||
cp.Rules[i2].Services[i4].Filters.Headers[i7].Set = make(map[string]string, len(o.Rules[i2].Services[i4].Filters.Headers[i7].Set))
|
||||
for k9, v9 := range o.Rules[i2].Services[i4].Filters.Headers[i7].Set {
|
||||
cp.Rules[i2].Services[i4].Filters.Headers[i7].Set[k9] = v9
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if o.Hostnames != nil {
|
||||
cp.Hostnames = make([]string, len(o.Hostnames))
|
||||
copy(cp.Hostnames, o.Hostnames)
|
||||
}
|
||||
if o.Meta != nil {
|
||||
cp.Meta = make(map[string]string, len(o.Meta))
|
||||
for k2, v2 := range o.Meta {
|
||||
cp.Meta[k2] = v2
|
||||
}
|
||||
}
|
||||
{
|
||||
retV := o.Status.DeepCopy()
|
||||
cp.Status = *retV
|
||||
}
|
||||
return &cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of *HashPolicy
|
||||
func (o *HashPolicy) DeepCopy() *HashPolicy {
|
||||
var cp HashPolicy = *o
|
||||
|
@ -369,6 +491,18 @@ func (o *IngressListener) DeepCopy() *IngressListener {
|
|||
return &cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of *InlineCertificateConfigEntry
|
||||
func (o *InlineCertificateConfigEntry) DeepCopy() *InlineCertificateConfigEntry {
|
||||
var cp InlineCertificateConfigEntry = *o
|
||||
if o.Meta != nil {
|
||||
cp.Meta = make(map[string]string, len(o.Meta))
|
||||
for k2, v2 := range o.Meta {
|
||||
cp.Meta[k2] = v2
|
||||
}
|
||||
}
|
||||
return &cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of *Intention
|
||||
func (o *Intention) DeepCopy() *Intention {
|
||||
var cp Intention = *o
|
||||
|
@ -809,6 +943,30 @@ func (o *ServiceRouteMatch) DeepCopy() *ServiceRouteMatch {
|
|||
return &cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of *TCPRouteConfigEntry
|
||||
func (o *TCPRouteConfigEntry) DeepCopy() *TCPRouteConfigEntry {
|
||||
var cp TCPRouteConfigEntry = *o
|
||||
if o.Parents != nil {
|
||||
cp.Parents = make([]ResourceReference, len(o.Parents))
|
||||
copy(cp.Parents, o.Parents)
|
||||
}
|
||||
if o.Services != nil {
|
||||
cp.Services = make([]TCPService, len(o.Services))
|
||||
copy(cp.Services, o.Services)
|
||||
}
|
||||
if o.Meta != nil {
|
||||
cp.Meta = make(map[string]string, len(o.Meta))
|
||||
for k2, v2 := range o.Meta {
|
||||
cp.Meta[k2] = v2
|
||||
}
|
||||
}
|
||||
{
|
||||
retV := o.Status.DeepCopy()
|
||||
cp.Status = *retV
|
||||
}
|
||||
return &cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of *Upstream
|
||||
func (o *Upstream) DeepCopy() *Upstream {
|
||||
var cp Upstream = *o
|
||||
|
@ -920,13 +1078,9 @@ func (o *BoundAPIGatewayConfigEntry) DeepCopy() *BoundAPIGatewayConfigEntry {
|
|||
cp.Listeners = make([]BoundAPIGatewayListener, len(o.Listeners))
|
||||
copy(cp.Listeners, o.Listeners)
|
||||
for i2 := range o.Listeners {
|
||||
if o.Listeners[i2].Routes != nil {
|
||||
cp.Listeners[i2].Routes = make([]ResourceReference, len(o.Listeners[i2].Routes))
|
||||
copy(cp.Listeners[i2].Routes, o.Listeners[i2].Routes)
|
||||
}
|
||||
if o.Listeners[i2].Certificates != nil {
|
||||
cp.Listeners[i2].Certificates = make([]ResourceReference, len(o.Listeners[i2].Certificates))
|
||||
copy(cp.Listeners[i2].Certificates, o.Listeners[i2].Certificates)
|
||||
{
|
||||
retV := o.Listeners[i2].DeepCopy()
|
||||
cp.Listeners[i2] = *retV
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1193,7 +1193,8 @@ func (k ServiceKind) IsProxy() bool {
|
|||
case ServiceKindConnectProxy,
|
||||
ServiceKindMeshGateway,
|
||||
ServiceKindTerminatingGateway,
|
||||
ServiceKindIngressGateway:
|
||||
ServiceKindIngressGateway,
|
||||
ServiceKindAPIGateway:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -1206,26 +1207,31 @@ const (
|
|||
// default to the typical service.
|
||||
ServiceKindTypical ServiceKind = ""
|
||||
|
||||
// ServiceKindConnectProxy is a proxy for the Connect feature. This
|
||||
// ServiceKindConnectProxy is a proxy for the Consul Service Mesh. This
|
||||
// service proxies another service within Consul and speaks the connect
|
||||
// protocol.
|
||||
ServiceKindConnectProxy ServiceKind = "connect-proxy"
|
||||
|
||||
// ServiceKindMeshGateway is a Mesh Gateway for the Connect feature. This
|
||||
// service will proxy connections based off the SNI header set by other
|
||||
// ServiceKindMeshGateway is a Mesh Gateway for the Consul Service Mesh.
|
||||
// This service will proxy connections based off the SNI header set by other
|
||||
// connect proxies
|
||||
ServiceKindMeshGateway ServiceKind = "mesh-gateway"
|
||||
|
||||
// ServiceKindTerminatingGateway is a Terminating Gateway for the Connect
|
||||
// feature. This service will proxy connections to services outside the mesh.
|
||||
// ServiceKindTerminatingGateway is a Terminating Gateway for the Consul Service
|
||||
// Mesh feature. This service will proxy connections to services outside the mesh.
|
||||
ServiceKindTerminatingGateway ServiceKind = "terminating-gateway"
|
||||
|
||||
// ServiceKindIngressGateway is an Ingress Gateway for the Connect feature.
|
||||
// ServiceKindIngressGateway is an Ingress Gateway for the Consul Service Mesh.
|
||||
// This service allows external traffic to enter the mesh based on
|
||||
// centralized configuration.
|
||||
ServiceKindIngressGateway ServiceKind = "ingress-gateway"
|
||||
|
||||
// ServiceKindDestination is a Destination for the Connect feature.
|
||||
// ServiceKindAPIGateway is an API Gateway for the Consul Service Mesh.
|
||||
// This service allows external traffic to enter the mesh based on
|
||||
// centralized configuration.
|
||||
ServiceKindAPIGateway ServiceKind = "api-gateway"
|
||||
|
||||
// ServiceKindDestination is a Destination for the Consul Service Mesh feature.
|
||||
// This service allows external traffic to exit the mesh through a terminating gateway
|
||||
// based on centralized configuration.
|
||||
ServiceKindDestination ServiceKind = "destination"
|
||||
|
@ -1424,7 +1430,8 @@ func (s *NodeService) IsSidecarProxy() bool {
|
|||
func (s *NodeService) IsGateway() bool {
|
||||
return s.Kind == ServiceKindMeshGateway ||
|
||||
s.Kind == ServiceKindTerminatingGateway ||
|
||||
s.Kind == ServiceKindIngressGateway
|
||||
s.Kind == ServiceKindIngressGateway ||
|
||||
s.Kind == ServiceKindAPIGateway
|
||||
}
|
||||
|
||||
// Validate validates the node service configuration.
|
||||
|
|
|
@ -61,6 +61,14 @@ func (s *ResourceGenerator) clustersFromSnapshot(cfgSnap *proxycfg.ConfigSnapsho
|
|||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
case structs.ServiceKindAPIGateway:
|
||||
// TODO Find a cleaner solution, can't currently pass unexported property types
|
||||
cfgSnap.IngressGateway = cfgSnap.APIGateway.ToIngress()
|
||||
res, err := s.clustersFromSnapshotIngressGateway(cfgSnap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("Invalid service kind: %v", cfgSnap.Kind)
|
||||
}
|
||||
|
|
|
@ -129,19 +129,24 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove
|
|||
// Configure handlers for each type of request we currently care about.
|
||||
handlers := map[string]*xDSDeltaType{
|
||||
xdscommon.ListenerType: newDeltaType(generator, stream, xdscommon.ListenerType, func(kind structs.ServiceKind) bool {
|
||||
return cfgSnap.Kind == structs.ServiceKindIngressGateway
|
||||
// Ingress and API gateways are allowed to inform LDS of no listeners.
|
||||
return cfgSnap.Kind == structs.ServiceKindIngressGateway ||
|
||||
cfgSnap.Kind == structs.ServiceKindAPIGateway
|
||||
}),
|
||||
xdscommon.RouteType: newDeltaType(generator, stream, xdscommon.RouteType, func(kind structs.ServiceKind) bool {
|
||||
return cfgSnap.Kind == structs.ServiceKindIngressGateway
|
||||
// Ingress and API gateways are allowed to inform RDS of no routes.
|
||||
return cfgSnap.Kind == structs.ServiceKindIngressGateway ||
|
||||
cfgSnap.Kind == structs.ServiceKindAPIGateway
|
||||
}),
|
||||
xdscommon.ClusterType: newDeltaType(generator, stream, xdscommon.ClusterType, func(kind structs.ServiceKind) bool {
|
||||
// Mesh, Ingress, and Terminating gateways are allowed to inform CDS of
|
||||
// no clusters.
|
||||
// Mesh, Ingress, API and Terminating gateways are allowed to inform CDS of no clusters.
|
||||
return cfgSnap.Kind == structs.ServiceKindMeshGateway ||
|
||||
cfgSnap.Kind == structs.ServiceKindTerminatingGateway ||
|
||||
cfgSnap.Kind == structs.ServiceKindIngressGateway
|
||||
cfgSnap.Kind == structs.ServiceKindIngressGateway ||
|
||||
cfgSnap.Kind == structs.ServiceKindAPIGateway
|
||||
}),
|
||||
xdscommon.EndpointType: newDeltaType(generator, stream, xdscommon.EndpointType, nil),
|
||||
xdscommon.SecretType: newDeltaType(generator, stream, xdscommon.SecretType, nil), // TODO allowEmptyFn
|
||||
}
|
||||
|
||||
// Endpoints are stored within a Cluster (and Routes
|
||||
|
@ -332,7 +337,7 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove
|
|||
|
||||
generator.Logger.Trace("Got initial config snapshot")
|
||||
|
||||
// Lets actually process the config we just got or we'll mis responding
|
||||
// Let's actually process the config we just got, or we'll miss responding
|
||||
fallthrough
|
||||
case stateDeltaRunning:
|
||||
// Check ACLs on every Discovery{Request,Response}.
|
||||
|
@ -462,6 +467,8 @@ func (s *Server) applyEnvoyExtensions(resources *xdscommon.IndexedResources, cfg
|
|||
}
|
||||
|
||||
var xDSUpdateOrder = []xDSUpdateOperation{
|
||||
// TODO Update comments
|
||||
{TypeUrl: xdscommon.SecretType, Upsert: true},
|
||||
// 1. CDS updates (if any) must always be pushed first.
|
||||
{TypeUrl: xdscommon.ClusterType, Upsert: true},
|
||||
// 2. EDS updates (if any) must arrive after CDS updates for the respective clusters.
|
||||
|
@ -472,9 +479,10 @@ var xDSUpdateOrder = []xDSUpdateOperation{
|
|||
{TypeUrl: xdscommon.RouteType, Upsert: true, Remove: true},
|
||||
// 5. (NOT IMPLEMENTED YET IN CONSUL) VHDS updates (if any) related to the newly added RouteConfigurations must arrive after RDS updates.
|
||||
// {},
|
||||
// 6. Stale CDS clusters and related EDS endpoints (ones no longer being referenced) can then be removed.
|
||||
// 6. Stale CDS clusters, related EDS endpoints (ones no longer being referenced) and SDS secrets can then be removed.
|
||||
{TypeUrl: xdscommon.ClusterType, Remove: true},
|
||||
{TypeUrl: xdscommon.EndpointType, Remove: true},
|
||||
{TypeUrl: xdscommon.SecretType, Remove: true},
|
||||
// xDS updates can be pushed independently if no new
|
||||
// clusters/routes/listeners are added or if it’s acceptable to
|
||||
// temporarily drop traffic during updates. Note that in case of
|
||||
|
|
|
@ -37,6 +37,10 @@ func (s *ResourceGenerator) endpointsFromSnapshot(cfgSnap *proxycfg.ConfigSnapsh
|
|||
return s.endpointsFromSnapshotMeshGateway(cfgSnap)
|
||||
case structs.ServiceKindIngressGateway:
|
||||
return s.endpointsFromSnapshotIngressGateway(cfgSnap)
|
||||
case structs.ServiceKindAPIGateway:
|
||||
// TODO Find a cleaner solution, can't currently pass unexported property types
|
||||
cfgSnap.IngressGateway = cfgSnap.APIGateway.ToIngress()
|
||||
return s.endpointsFromSnapshotIngressGateway(cfgSnap)
|
||||
default:
|
||||
return nil, fmt.Errorf("Invalid service kind: %v", cfgSnap.Kind)
|
||||
}
|
||||
|
|
|
@ -58,11 +58,10 @@ func (s *ResourceGenerator) listenersFromSnapshot(cfgSnap *proxycfg.ConfigSnapsh
|
|||
switch cfgSnap.Kind {
|
||||
case structs.ServiceKindConnectProxy:
|
||||
return s.listenersFromSnapshotConnectProxy(cfgSnap)
|
||||
case structs.ServiceKindTerminatingGateway:
|
||||
return s.listenersFromSnapshotGateway(cfgSnap)
|
||||
case structs.ServiceKindMeshGateway:
|
||||
return s.listenersFromSnapshotGateway(cfgSnap)
|
||||
case structs.ServiceKindIngressGateway:
|
||||
case structs.ServiceKindTerminatingGateway,
|
||||
structs.ServiceKindMeshGateway,
|
||||
structs.ServiceKindIngressGateway,
|
||||
structs.ServiceKindAPIGateway:
|
||||
return s.listenersFromSnapshotGateway(cfgSnap)
|
||||
default:
|
||||
return nil, fmt.Errorf("Invalid service kind: %v", cfgSnap.Kind)
|
||||
|
@ -849,6 +848,14 @@ func (s *ResourceGenerator) listenersFromSnapshotGateway(cfgSnap *proxycfg.Confi
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case structs.ServiceKindAPIGateway:
|
||||
// TODO Find a cleaner solution, can't currently pass unexported property types
|
||||
cfgSnap.IngressGateway = cfgSnap.APIGateway.ToIngress()
|
||||
listeners, err := s.makeIngressGatewayListeners(a.Address, cfgSnap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resources = append(resources, listeners...)
|
||||
case structs.ServiceKindIngressGateway:
|
||||
listeners, err := s.makeIngressGatewayListeners(a.Address, cfgSnap)
|
||||
if err != nil {
|
||||
|
|
|
@ -3,10 +3,11 @@ package xds
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/consul/envoyextensions/xdscommon"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/hashicorp/consul/envoyextensions/xdscommon"
|
||||
|
||||
"github.com/hashicorp/consul/agent/proxycfg"
|
||||
)
|
||||
|
||||
|
@ -34,6 +35,7 @@ func NewResourceGenerator(
|
|||
|
||||
func (g *ResourceGenerator) AllResourcesFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) (map[string][]proto.Message, error) {
|
||||
all := make(map[string][]proto.Message)
|
||||
// TODO Add xdscommon.SecretType
|
||||
for _, typeUrl := range []string{xdscommon.ListenerType, xdscommon.RouteType, xdscommon.ClusterType, xdscommon.EndpointType} {
|
||||
res, err := g.resourcesFromSnapshot(typeUrl, cfgSnap)
|
||||
if err != nil {
|
||||
|
@ -54,6 +56,8 @@ func (g *ResourceGenerator) resourcesFromSnapshot(typeUrl string, cfgSnap *proxy
|
|||
return g.clustersFromSnapshot(cfgSnap)
|
||||
case xdscommon.EndpointType:
|
||||
return g.endpointsFromSnapshot(cfgSnap)
|
||||
case xdscommon.SecretType:
|
||||
return g.secretsFromSnapshot(cfgSnap)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown typeUrl: %s", typeUrl)
|
||||
}
|
||||
|
|
|
@ -32,6 +32,10 @@ func (s *ResourceGenerator) routesFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot)
|
|||
return s.routesForConnectProxy(cfgSnap)
|
||||
case structs.ServiceKindIngressGateway:
|
||||
return s.routesForIngressGateway(cfgSnap)
|
||||
case structs.ServiceKindAPIGateway:
|
||||
// TODO Find a cleaner solution, can't currently pass unexported property types
|
||||
cfgSnap.IngressGateway = cfgSnap.APIGateway.ToIngress()
|
||||
return s.routesForIngressGateway(cfgSnap)
|
||||
case structs.ServiceKindTerminatingGateway:
|
||||
return s.routesForTerminatingGateway(cfgSnap)
|
||||
case structs.ServiceKindMeshGateway:
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package xds
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/hashicorp/consul/agent/proxycfg"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
)
|
||||
|
||||
// secretsFromSnapshot returns the xDS API representation of the "secrets"
|
||||
// in the snapshot
|
||||
func (s *ResourceGenerator) secretsFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||
if cfgSnap == nil {
|
||||
return nil, errors.New("nil config given")
|
||||
}
|
||||
|
||||
switch cfgSnap.Kind {
|
||||
case structs.ServiceKindConnectProxy,
|
||||
structs.ServiceKindTerminatingGateway,
|
||||
structs.ServiceKindMeshGateway,
|
||||
structs.ServiceKindIngressGateway:
|
||||
return nil, nil
|
||||
// Only API gateways utilize secrets
|
||||
case structs.ServiceKindAPIGateway:
|
||||
return s.secretsFromSnapshotAPIGateway(cfgSnap)
|
||||
default:
|
||||
return nil, fmt.Errorf("Invalid service kind: %v", cfgSnap.Kind)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ResourceGenerator) secretsFromSnapshotAPIGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||
var res []proto.Message
|
||||
// TODO
|
||||
return res, nil
|
||||
}
|
|
@ -229,7 +229,7 @@ func (s *Server) authorize(ctx context.Context, cfgSnap *proxycfg.ConfigSnapshot
|
|||
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(cfgSnap.Proxy.DestinationServiceName, &authzContext); err != nil {
|
||||
return status.Errorf(codes.PermissionDenied, err.Error())
|
||||
}
|
||||
case structs.ServiceKindMeshGateway, structs.ServiceKindTerminatingGateway, structs.ServiceKindIngressGateway:
|
||||
case structs.ServiceKindMeshGateway, structs.ServiceKindTerminatingGateway, structs.ServiceKindIngressGateway, structs.ServiceKindAPIGateway:
|
||||
cfgSnap.ProxyID.EnterpriseMeta.FillAuthzContext(&authzContext)
|
||||
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(cfgSnap.Service, &authzContext); err != nil {
|
||||
return status.Errorf(codes.PermissionDenied, err.Error())
|
||||
|
|
|
@ -46,6 +46,9 @@ const (
|
|||
|
||||
// ListenerType is the TypeURL for Listener discovery responses.
|
||||
ListenerType = apiTypePrefix + "envoy.config.listener.v3.Listener"
|
||||
|
||||
// SecretType is the TypeURL for Secret discovery responses.
|
||||
SecretType = apiTypePrefix + "envoy.extensions.transport_sockets.tls.v3.Secret"
|
||||
)
|
||||
|
||||
type IndexedResources struct {
|
||||
|
|
|
@ -102,6 +102,9 @@ const (
|
|||
// ServiceKind Ingress Gateway is an Ingress Gateway for the Connect feature.
|
||||
// This service will ingress connections into the service mesh.
|
||||
ServiceKind_SERVICE_KIND_INGRESS_GATEWAY ServiceKind = 5
|
||||
// ServiceKind API Gateway is an API Gateway for the Connect feature.
|
||||
// This service will ingress connections in to the service mesh.
|
||||
ServiceKind_SERVICE_KIND_API_GATEWAY ServiceKind = 6
|
||||
)
|
||||
|
||||
// Enum value maps for ServiceKind.
|
||||
|
@ -113,6 +116,7 @@ var (
|
|||
3: "SERVICE_KIND_MESH_GATEWAY",
|
||||
4: "SERVICE_KIND_TERMINATING_GATEWAY",
|
||||
5: "SERVICE_KIND_INGRESS_GATEWAY",
|
||||
6: "SERVICE_KIND_API_GATEWAY",
|
||||
}
|
||||
ServiceKind_value = map[string]int32{
|
||||
"SERVICE_KIND_UNSPECIFIED": 0,
|
||||
|
@ -121,6 +125,7 @@ var (
|
|||
"SERVICE_KIND_MESH_GATEWAY": 3,
|
||||
"SERVICE_KIND_TERMINATING_GATEWAY": 4,
|
||||
"SERVICE_KIND_INGRESS_GATEWAY": 5,
|
||||
"SERVICE_KIND_API_GATEWAY": 6,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -593,7 +598,7 @@ var file_proto_public_pbdataplane_dataplane_proto_rawDesc = []byte{
|
|||
0x4e, 0x54, 0x10, 0x02, 0x12, 0x34, 0x0a, 0x30, 0x44, 0x41, 0x54, 0x41, 0x50, 0x4c, 0x41, 0x4e,
|
||||
0x45, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x53, 0x5f, 0x45, 0x4e, 0x56, 0x4f, 0x59,
|
||||
0x5f, 0x42, 0x4f, 0x4f, 0x54, 0x53, 0x54, 0x52, 0x41, 0x50, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49,
|
||||
0x47, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x2a, 0xcc, 0x01, 0x0a, 0x0b, 0x53,
|
||||
0x47, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x2a, 0xea, 0x01, 0x0a, 0x0b, 0x53,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x45,
|
||||
0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
|
||||
0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x45, 0x52, 0x56,
|
||||
|
@ -606,45 +611,47 @@ var file_proto_public_pbdataplane_dataplane_proto_rawDesc = []byte{
|
|||
0x44, 0x5f, 0x54, 0x45, 0x52, 0x4d, 0x49, 0x4e, 0x41, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x41,
|
||||
0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x04, 0x12, 0x20, 0x0a, 0x1c, 0x53, 0x45, 0x52, 0x56, 0x49,
|
||||
0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x49, 0x4e, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f,
|
||||
0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x05, 0x32, 0xde, 0x02, 0x0a, 0x10, 0x44, 0x61,
|
||||
0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xac,
|
||||
0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44,
|
||||
0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73,
|
||||
0x12, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x05, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x45, 0x52,
|
||||
0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x47, 0x41,
|
||||
0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x06, 0x32, 0xde, 0x02, 0x0a, 0x10, 0x44, 0x61, 0x74, 0x61,
|
||||
0x70, 0x6c, 0x61, 0x6e, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xac, 0x01, 0x0a,
|
||||
0x1d, 0x47, 0x65, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74,
|
||||
0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x40,
|
||||
0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75,
|
||||
0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53,
|
||||
0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e,
|
||||
0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x65,
|
||||
0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c,
|
||||
0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63,
|
||||
0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e,
|
||||
0x47, 0x65, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61,
|
||||
0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xe2, 0x86, 0x04, 0x02, 0x08, 0x02, 0x12, 0x9a, 0x01,
|
||||
0x0a, 0x17, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74,
|
||||
0x72, 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68,
|
||||
0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74,
|
||||
0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42,
|
||||
0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72,
|
||||
0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61,
|
||||
0x6e, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, 0x6f, 0x74, 0x73,
|
||||
0x74, 0x72, 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x22, 0x06, 0xe2, 0x86, 0x04, 0x02, 0x08, 0x02, 0x42, 0xf0, 0x01, 0x0a, 0x1e, 0x63,
|
||||
0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x42, 0x0e, 0x44,
|
||||
0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a,
|
||||
0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68,
|
||||
0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x64, 0x61, 0x74, 0x61,
|
||||
0x70, 0x6c, 0x61, 0x6e, 0x65, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x44, 0xaa, 0x02, 0x1a, 0x48, 0x61,
|
||||
0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x44,
|
||||
0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0xca, 0x02, 0x1a, 0x48, 0x61, 0x73, 0x68, 0x69,
|
||||
0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x44, 0x61, 0x74, 0x61,
|
||||
0x70, 0x6c, 0x61, 0x6e, 0x65, 0xe2, 0x02, 0x26, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72,
|
||||
0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61,
|
||||
0x6e, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02,
|
||||
0x1c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73,
|
||||
0x75, 0x6c, 0x3a, 0x3a, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x62, 0x06, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x06, 0xe2, 0x86, 0x04, 0x02, 0x08, 0x02, 0x12, 0x9a, 0x01, 0x0a, 0x17,
|
||||
0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61,
|
||||
0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63,
|
||||
0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70,
|
||||
0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, 0x6f,
|
||||
0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e,
|
||||
0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65,
|
||||
0x2e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72,
|
||||
0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x22, 0x06, 0xe2, 0x86, 0x04, 0x02, 0x08, 0x02, 0x42, 0xf0, 0x01, 0x0a, 0x1e, 0x63, 0x6f, 0x6d,
|
||||
0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75,
|
||||
0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x42, 0x0e, 0x44, 0x61, 0x74,
|
||||
0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x34, 0x67,
|
||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63,
|
||||
0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c,
|
||||
0x61, 0x6e, 0x65, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x44, 0xaa, 0x02, 0x1a, 0x48, 0x61, 0x73, 0x68,
|
||||
0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x44, 0x61, 0x74,
|
||||
0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0xca, 0x02, 0x1a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f,
|
||||
0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c,
|
||||
0x61, 0x6e, 0x65, 0xe2, 0x02, 0x26, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c,
|
||||
0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65,
|
||||
0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1c, 0x48,
|
||||
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
|
||||
0x3a, 0x3a, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
@ -65,6 +65,10 @@ enum ServiceKind {
|
|||
// ServiceKind Ingress Gateway is an Ingress Gateway for the Connect feature.
|
||||
// This service will ingress connections into the service mesh.
|
||||
SERVICE_KIND_INGRESS_GATEWAY = 5;
|
||||
|
||||
// ServiceKind API Gateway is an API Gateway for the Connect feature.
|
||||
// This service will ingress connections in to the service mesh.
|
||||
SERVICE_KIND_API_GATEWAY = 6;
|
||||
}
|
||||
|
||||
message GetEnvoyBootstrapParamsResponse {
|
||||
|
|
Loading…
Reference in New Issue