Add http routing support and integration test to ingress gateways
This commit is contained in:
parent
ef88089924
commit
d433679bd8
|
@ -23,6 +23,8 @@ func routesFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot, _ string) ([]proto.Mes
|
|||
switch cfgSnap.Kind {
|
||||
case structs.ServiceKindConnectProxy:
|
||||
return routesFromSnapshotConnectProxy(cfgSnap)
|
||||
case structs.ServiceKindIngressGateway:
|
||||
return routesFromSnapshotIngressGateway(cfgSnap)
|
||||
default:
|
||||
return nil, fmt.Errorf("Invalid service kind: %v", cfgSnap.Kind)
|
||||
}
|
||||
|
@ -35,20 +37,34 @@ func routesFromSnapshotConnectProxy(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.M
|
|||
return nil, errors.New("nil config given")
|
||||
}
|
||||
|
||||
return routesFromUpstreams(cfgSnap.ConnectProxy.ConfigSnapshotUpstreams, cfgSnap.Proxy.Upstreams)
|
||||
}
|
||||
|
||||
// routesFromSnapshotIngressGateway returns the xDS API representation of the
|
||||
// "routes" in the snapshot.
|
||||
func routesFromSnapshotIngressGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||
if cfgSnap == nil {
|
||||
return nil, errors.New("nil config given")
|
||||
}
|
||||
|
||||
return routesFromUpstreams(cfgSnap.IngressGateway.ConfigSnapshotUpstreams, cfgSnap.IngressGateway.Upstreams)
|
||||
}
|
||||
|
||||
func routesFromUpstreams(snap proxycfg.ConfigSnapshotUpstreams, upstreams structs.Upstreams) ([]proto.Message, error) {
|
||||
var resources []proto.Message
|
||||
|
||||
for _, u := range cfgSnap.Proxy.Upstreams {
|
||||
for _, u := range upstreams {
|
||||
upstreamID := u.Identifier()
|
||||
|
||||
var chain *structs.CompiledDiscoveryChain
|
||||
if u.DestinationType != structs.UpstreamDestTypePreparedQuery {
|
||||
chain = cfgSnap.ConnectProxy.DiscoveryChain[upstreamID]
|
||||
chain = snap.DiscoveryChain[upstreamID]
|
||||
}
|
||||
|
||||
if chain == nil || chain.IsDefault() {
|
||||
// TODO(rb): make this do the old school stuff too
|
||||
} else {
|
||||
upstreamRoute, err := makeUpstreamRouteForDiscoveryChain(&u, chain, cfgSnap)
|
||||
upstreamRoute, err := makeUpstreamRouteForDiscoveryChain(&u, chain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -66,7 +82,6 @@ func routesFromSnapshotConnectProxy(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.M
|
|||
func makeUpstreamRouteForDiscoveryChain(
|
||||
u *structs.Upstream,
|
||||
chain *structs.CompiledDiscoveryChain,
|
||||
cfgSnap *proxycfg.ConfigSnapshot,
|
||||
) (*envoy.RouteConfiguration, error) {
|
||||
upstreamID := u.Identifier()
|
||||
routeName := upstreamID
|
||||
|
@ -93,13 +108,13 @@ func makeUpstreamRouteForDiscoveryChain(
|
|||
nextNode := chain.Nodes[discoveryRoute.NextNode]
|
||||
switch nextNode.Type {
|
||||
case structs.DiscoveryGraphNodeTypeSplitter:
|
||||
routeAction, err = makeRouteActionForSplitter(nextNode.Splits, chain, cfgSnap)
|
||||
routeAction, err = makeRouteActionForSplitter(nextNode.Splits, chain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
case structs.DiscoveryGraphNodeTypeResolver:
|
||||
routeAction = makeRouteActionForSingleCluster(nextNode.Resolver.Target, chain, cfgSnap)
|
||||
routeAction = makeRouteActionForSingleCluster(nextNode.Resolver.Target, chain)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected graph node after route %q", nextNode.Type)
|
||||
|
@ -147,7 +162,7 @@ func makeUpstreamRouteForDiscoveryChain(
|
|||
}
|
||||
|
||||
case structs.DiscoveryGraphNodeTypeSplitter:
|
||||
routeAction, err := makeRouteActionForSplitter(startNode.Splits, chain, cfgSnap)
|
||||
routeAction, err := makeRouteActionForSplitter(startNode.Splits, chain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -160,7 +175,7 @@ func makeUpstreamRouteForDiscoveryChain(
|
|||
routes = []envoyroute.Route{defaultRoute}
|
||||
|
||||
case structs.DiscoveryGraphNodeTypeResolver:
|
||||
routeAction := makeRouteActionForSingleCluster(startNode.Resolver.Target, chain, cfgSnap)
|
||||
routeAction := makeRouteActionForSingleCluster(startNode.Resolver.Target, chain)
|
||||
|
||||
defaultRoute := envoyroute.Route{
|
||||
Match: makeDefaultRouteMatch(),
|
||||
|
@ -307,7 +322,7 @@ func makeDefaultRouteMatch() envoyroute.RouteMatch {
|
|||
}
|
||||
}
|
||||
|
||||
func makeRouteActionForSingleCluster(targetID string, chain *structs.CompiledDiscoveryChain, cfgSnap *proxycfg.ConfigSnapshot) *envoyroute.Route_Route {
|
||||
func makeRouteActionForSingleCluster(targetID string, chain *structs.CompiledDiscoveryChain) *envoyroute.Route_Route {
|
||||
target := chain.Targets[targetID]
|
||||
|
||||
clusterName := CustomizeClusterName(target.Name, chain)
|
||||
|
@ -321,7 +336,7 @@ func makeRouteActionForSingleCluster(targetID string, chain *structs.CompiledDis
|
|||
}
|
||||
}
|
||||
|
||||
func makeRouteActionForSplitter(splits []*structs.DiscoverySplit, chain *structs.CompiledDiscoveryChain, cfgSnap *proxycfg.ConfigSnapshot) (*envoyroute.Route_Route, error) {
|
||||
func makeRouteActionForSplitter(splits []*structs.DiscoverySplit, chain *structs.CompiledDiscoveryChain) (*envoyroute.Route_Route, error) {
|
||||
clusters := make([]*envoyroute.WeightedCluster_ClusterWeight, 0, len(splits))
|
||||
for _, split := range splits {
|
||||
nextNode := chain.Nodes[split.NextNode]
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
snapshot_envoy_admin localhost:20000 ingress-gateway primary || true
|
|
@ -0,0 +1,62 @@
|
|||
enable_central_service_config = true
|
||||
|
||||
config_entries {
|
||||
bootstrap = [
|
||||
{
|
||||
kind = "ingress-gateway"
|
||||
name = "ingress-gateway"
|
||||
|
||||
listeners = [
|
||||
{
|
||||
port = 9999
|
||||
protocol = "http"
|
||||
services = [
|
||||
{
|
||||
name = "router"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
kind = "proxy-defaults"
|
||||
name = "global"
|
||||
config {
|
||||
protocol = "http"
|
||||
}
|
||||
},
|
||||
{
|
||||
kind = "service-router"
|
||||
// This is a "virtual" service name and will not have a backing
|
||||
// service definition. It must match the name defined in the ingress
|
||||
// configuration.
|
||||
name = "router"
|
||||
routes = [
|
||||
{
|
||||
match {
|
||||
http {
|
||||
path_prefix = "/s1/"
|
||||
}
|
||||
}
|
||||
|
||||
destination {
|
||||
service = "s1"
|
||||
prefix_rewrite = "/"
|
||||
}
|
||||
},
|
||||
{
|
||||
match {
|
||||
http {
|
||||
path_prefix = "/s2/"
|
||||
}
|
||||
}
|
||||
|
||||
destination {
|
||||
service = "s2"
|
||||
prefix_rewrite = "/"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
services {
|
||||
name = "ingress-gateway"
|
||||
kind = "ingress-gateway"
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# wait for bootstrap to apply config entries
|
||||
wait_for_config_entry ingress-gateway ingress-gateway
|
||||
wait_for_config_entry proxy-defaults global
|
||||
wait_for_config_entry service-router router
|
||||
|
||||
gen_envoy_bootstrap ingress-gateway 20000 primary true
|
||||
gen_envoy_bootstrap s1 19000
|
||||
gen_envoy_bootstrap s2 19001
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES ingress-gateway-primary"
|
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load helpers
|
||||
|
||||
@test "ingress proxy admin is up on :20000" {
|
||||
retry_default curl -f -s localhost:20000/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "s1 proxy admin is up on :19000" {
|
||||
retry_default curl -f -s localhost:19000/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "s2 proxy admin is up on :19001" {
|
||||
retry_default curl -f -s localhost:19001/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "s1 proxy listener should be up and have right cert" {
|
||||
assert_proxy_presents_cert_uri localhost:21000 s1
|
||||
}
|
||||
|
||||
@test "s2 proxy listener should be up and have right cert" {
|
||||
assert_proxy_presents_cert_uri localhost:21001 s2
|
||||
}
|
||||
|
||||
@test "ingress-gateway should have healthy endpoints for s1" {
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:20000 s1 HEALTHY 1
|
||||
}
|
||||
|
||||
@test "ingress-gateway should have healthy endpoints for s2" {
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:20000 s2 HEALTHY 1
|
||||
}
|
||||
|
||||
@test "ingress should be able to connect to s1 via configured path" {
|
||||
run retry_default curl -s -f localhost:9999/s1/debug?env=dump
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
GOT=$(echo "$output" | grep -E "^FORTIO_NAME=")
|
||||
EXPECT_NAME="s1"
|
||||
|
||||
if [ "$GOT" != "FORTIO_NAME=${EXPECT_NAME}" ]; then
|
||||
echo "expected name: $EXPECT_NAME, actual name: $GOT" 1>&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
@test "ingress should be able to connect to s2 via configured path" {
|
||||
run retry_default curl -s -f localhost:9999/s2/debug?env=dump
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
GOT=$(echo "$output" | grep -E "^FORTIO_NAME=")
|
||||
EXPECT_NAME="s2"
|
||||
|
||||
if [ "$GOT" != "FORTIO_NAME=${EXPECT_NAME}" ]; then
|
||||
echo "expected name: $EXPECT_NAME, actual name: $GOT" 1>&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
Loading…
Reference in New Issue