Skip to content

Commit

Permalink
add more methods to control bootstrap config
Browse files Browse the repository at this point in the history
Signed-off-by: spacewander <[email protected]>
  • Loading branch information
spacewander committed Jan 10, 2025
1 parent 982b45c commit 00e4670
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 21 deletions.
54 changes: 42 additions & 12 deletions api/plugins/tests/integration/controlplane/control_plane.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ import (

var (
logger = log.DefaultLogger.WithName("controlplane")

FeatureTestEnvoyDynamicCluster = "x-test-envoy-dynamic-cluster"
DynamicClusterHeader = "Cluster-Name"
)

type ControlPlane struct {
Expand Down Expand Up @@ -150,7 +153,31 @@ func (cp *ControlPlane) updateConfig(t *testing.T, res Resources) {
}

func (cp *ControlPlane) UseGoPluginConfig(t *testing.T, config *filtermanager.FilterManagerConfig, dp *dataplane.DataPlane) {
testRouteDynamicCluster := &route.Route{
Name: "dynamic-cluster",
Match: &route.RouteMatch{
PathSpecifier: &route.RouteMatch_Prefix{
Prefix: "/",
},
Headers: []*route.HeaderMatcher{
{
Name: FeatureTestEnvoyDynamicCluster,
HeaderMatchSpecifier: &route.HeaderMatcher_PresentMatch{
PresentMatch: true,
},
},
},
},
Action: &route.Route_Route{
Route: &route.RouteAction{
ClusterSpecifier: &route.RouteAction_ClusterHeader{
ClusterHeader: DynamicClusterHeader,
},
},
},
}
testRoute := &route.Route{
Name: "default",
Match: &route.RouteMatch{
PathSpecifier: &route.RouteMatch_Prefix{
Prefix: "/",
Expand All @@ -164,18 +191,22 @@ func (cp *ControlPlane) UseGoPluginConfig(t *testing.T, config *filtermanager.Fi
},
},
}
routes := []*route.Route{testRouteDynamicCluster, testRoute}

if config != nil {
testRoute.TypedPerFilterConfig = map[string]*any1.Any{
"htnn.filters.http.golang": proto.MessageToAny(&golang.ConfigsPerRoute{
PluginsConfig: map[string]*golang.RouterPlugin{
"fm": {
Override: &golang.RouterPlugin_Config{
Config: proto.MessageToAny(
FilterManagerConfigToTypedStruct(config)),
for _, r := range routes {
r.TypedPerFilterConfig = map[string]*any1.Any{
"htnn.filters.http.golang": proto.MessageToAny(&golang.ConfigsPerRoute{
PluginsConfig: map[string]*golang.RouterPlugin{
"fm": {
Override: &golang.RouterPlugin_Config{
Config: proto.MessageToAny(
FilterManagerConfigToTypedStruct(config)),
},
},
},
},
}),
}),
}
}
}

Expand All @@ -187,7 +218,7 @@ func (cp *ControlPlane) UseGoPluginConfig(t *testing.T, config *filtermanager.Fi
{
Name: "dynmamic_service",
Domains: []string{"*"},
Routes: []*route.Route{
Routes: append([]*route.Route{
{
Name: getRandomString(8),
Match: &route.RouteMatch{
Expand Down Expand Up @@ -237,8 +268,7 @@ func (cp *ControlPlane) UseGoPluginConfig(t *testing.T, config *filtermanager.Fi
}),
},
},
testRoute,
},
}, routes...),
},
},
},
Expand Down
57 changes: 48 additions & 9 deletions api/plugins/tests/integration/dataplane/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package dataplane
import (
_ "embed"
"encoding/json"
"io"
"math/rand"
"os"
"strconv"
Expand All @@ -29,21 +30,31 @@ var (
boostrapTemplate []byte
)

type HTTPFilterInsertOperation int

const (
HTTPFilterInsertOperationBeforeRouter HTTPFilterInsertOperation = iota
)

type bootstrap struct {
backendRoutes []map[string]interface{}
consumers map[string]map[string]interface{}
httpFilterGolang map[string]interface{}
accessLogFormat string
clusters []map[string]interface{}
backendRoutes []map[string]interface{}
consumers map[string]map[string]interface{}
httpFilterGolang map[string]interface{}
accessLogFormat string
clusters []map[string]interface{}
listeners []map[string]interface{}
insertedHTTPFilters map[HTTPFilterInsertOperation][]interface{}

dp *DataPlane
}

func Bootstrap() *bootstrap {
return &bootstrap{
backendRoutes: []map[string]interface{}{},
consumers: map[string]map[string]interface{}{},
clusters: []map[string]interface{}{},
backendRoutes: []map[string]interface{}{},
consumers: map[string]map[string]interface{}{},
clusters: []map[string]interface{}{},
listeners: []map[string]interface{}{},
insertedHTTPFilters: map[HTTPFilterInsertOperation][]interface{}{},
}
}

Expand Down Expand Up @@ -85,6 +96,11 @@ func (b *bootstrap) SetFilterGolang(cfg map[string]interface{}) *bootstrap {
return b
}

func (b *bootstrap) InsertHTTPFilter(cfg map[string]interface{}, op HTTPFilterInsertOperation) *bootstrap {
b.insertedHTTPFilters[op] = append(b.insertedHTTPFilters[op], cfg)
return b
}

func (b *bootstrap) SetAccessLogFormat(fmt string) *bootstrap {
b.accessLogFormat = fmt
return b
Expand All @@ -100,6 +116,16 @@ func (b *bootstrap) AddCluster(s string) *bootstrap {
return b
}

func (b *bootstrap) AddListener(s string) *bootstrap {
var n map[string]interface{}
err := yaml.Unmarshal([]byte(s), &n)
if err != nil {
panic(err)
}
b.listeners = append(b.listeners, n)
return b
}

func (b *bootstrap) buildConfiguration() (map[string]interface{}, error) {
var root map[string]interface{}
// check if the input is valid yaml
Expand Down Expand Up @@ -132,6 +158,13 @@ func (b *bootstrap) buildConfiguration() (map[string]interface{}, error) {
consumers[name] = c
}

if len(b.insertedHTTPFilters) > 0 {
routerFilter := httpFilters[len(httpFilters)-1]
httpFilters = append(httpFilters[:len(httpFilters)-1], b.insertedHTTPFilters[HTTPFilterInsertOperationBeforeRouter]...)
httpFilters = append(httpFilters, routerFilter)
hcm["http_filters"] = httpFilters
}

if b.httpFilterGolang != nil {
for _, hf := range httpFilters {
if hf.(map[string]interface{})["name"] == "htnn.filters.http.golang" {
Expand Down Expand Up @@ -176,6 +209,12 @@ func (b *bootstrap) buildConfiguration() (map[string]interface{}, error) {
}
staticResources["clusters"] = append(clusters, newClusters...)

newListeners := []interface{}{}
for _, l := range b.listeners {
newListeners = append(newListeners, l)
}
staticResources["listeners"] = append(staticResources["listeners"].([]interface{}), newListeners...)

addr := root["admin"].(map[string]interface{})["address"].(map[string]interface{})["socket_address"].(map[string]interface{})
addr["port_value"] = b.dp.AdminAPIPort()
addr = staticResources["listeners"].([]interface{})[0].(map[string]interface{})["address"].(map[string]interface{})["socket_address"].(map[string]interface{})
Expand Down Expand Up @@ -205,7 +244,7 @@ func (b *bootstrap) buildConfiguration() (map[string]interface{}, error) {
return root, nil
}

func (b *bootstrap) WriteTo(cfgFile *os.File) error {
func (b *bootstrap) WriteTo(cfgFile io.Writer) error {
root, err := b.buildConfiguration()
if err != nil {
return err
Expand Down
50 changes: 50 additions & 0 deletions api/plugins/tests/integration/dataplane/bootstrap_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package dataplane

import (
"bytes"
_ "embed"
"testing"

"github.com/stretchr/testify/assert"
)

var (
//go:embed testdata/listener.yml
listener string
)

func TestInsertHTTPFilterBeforeRouter(t *testing.T) {
dp := &DataPlane{
t: t,
opt: &Option{},
}
b := Bootstrap()
b.SetDataPlane(dp)
b.InsertHTTPFilter(map[string]interface{}{
"name": "test.filter.buffer",
"typed_config": map[string]interface{}{
"@type": "type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer",
"max_request_bytes": 1024,
},
}, HTTPFilterInsertOperationBeforeRouter)
buf := bytes.NewBuffer([]byte(""))
err := b.WriteTo(buf)
assert.Nil(t, err)
assert.Regexp(t, `- name: test.filter.buffer\s+typed_config:[^-]+- name: envoy.filters.http.router`, buf.String())
}

func TestAddListener(t *testing.T) {
dp := &DataPlane{
t: t,
opt: &Option{},
}
b := Bootstrap()
b.SetDataPlane(dp)
b.AddListener(listener)
buf := bytes.NewBuffer([]byte(""))
err := b.WriteTo(buf)
assert.Nil(t, err)
s := buf.String()
assert.Contains(t, s, "name: listener_proxy")
assert.Contains(t, s, "cluster: x_backend")
}
29 changes: 29 additions & 0 deletions api/plugins/tests/integration/dataplane/testdata/listener.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: listener_proxy
address:
socket_address:
address: 127.0.0.1
port_value: 10010
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
access_log:
- name: envoy.access_loggers.stdout
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: /
route:
cluster: x_backend

0 comments on commit 00e4670

Please sign in to comment.