...

Source file src/github.com/datawire/ambassador/v2/pkg/envoy-control-plane/test/resource/v3/resource.go

Documentation: github.com/datawire/ambassador/v2/pkg/envoy-control-plane/test/resource/v3

     1  // Code generated by create_version. DO NOT EDIT.
     2  // Copyright 2018 Envoyproxy Authors
     3  //
     4  //   Licensed under the Apache License, Version 2.0 (the "License");
     5  //   you may not use this file except in compliance with the License.
     6  //   You may obtain a copy of the License at
     7  //
     8  //       http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  //   Unless required by applicable law or agreed to in writing, software
    11  //   distributed under the License is distributed on an "AS IS" BASIS,
    12  //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  //   See the License for the specific language governing permissions and
    14  //   limitations under the License.
    15  
    16  // Package resource creates test xDS resources
    17  package resource
    18  
    19  import (
    20  	"fmt"
    21  	"time"
    22  
    23  	pstruct "github.com/golang/protobuf/ptypes/struct"
    24  
    25  	"github.com/golang/protobuf/ptypes"
    26  
    27  	alf "github.com/datawire/ambassador/v2/pkg/api/envoy/config/accesslog/v3"
    28  	cluster "github.com/datawire/ambassador/v2/pkg/api/envoy/config/cluster/v3"
    29  	core "github.com/datawire/ambassador/v2/pkg/api/envoy/config/core/v3"
    30  	endpoint "github.com/datawire/ambassador/v2/pkg/api/envoy/config/endpoint/v3"
    31  	endpointv2 "github.com/datawire/ambassador/v2/pkg/api/envoy/config/endpoint/v3"
    32  	listener "github.com/datawire/ambassador/v2/pkg/api/envoy/config/listener/v3"
    33  	listenerv2 "github.com/datawire/ambassador/v2/pkg/api/envoy/config/listener/v3"
    34  	route "github.com/datawire/ambassador/v2/pkg/api/envoy/config/route/v3"
    35  	routev2 "github.com/datawire/ambassador/v2/pkg/api/envoy/config/route/v3"
    36  	als "github.com/datawire/ambassador/v2/pkg/api/envoy/extensions/access_loggers/grpc/v3"
    37  	hcm "github.com/datawire/ambassador/v2/pkg/api/envoy/extensions/filters/network/http_connection_manager/v3"
    38  	tcp "github.com/datawire/ambassador/v2/pkg/api/envoy/extensions/filters/network/tcp_proxy/v3"
    39  	auth "github.com/datawire/ambassador/v2/pkg/api/envoy/extensions/transport_sockets/tls/v3"
    40  	runtime "github.com/datawire/ambassador/v2/pkg/api/envoy/service/runtime/v3"
    41  	"github.com/datawire/ambassador/v2/pkg/envoy-control-plane/cache/types"
    42  	"github.com/datawire/ambassador/v2/pkg/envoy-control-plane/cache/v3"
    43  	"github.com/datawire/ambassador/v2/pkg/envoy-control-plane/resource/v3"
    44  	"github.com/datawire/ambassador/v2/pkg/envoy-control-plane/wellknown"
    45  )
    46  
    47  const (
    48  	localhost = "127.0.0.1"
    49  
    50  	// XdsCluster is the cluster name for the control server (used by non-ADS set-up)
    51  	XdsCluster = "xds_cluster"
    52  
    53  	// Ads mode for resources: one aggregated xDS service
    54  	Ads = "ads"
    55  
    56  	// Xds mode for resources: individual xDS services
    57  	Xds = "xds"
    58  
    59  	// Rest mode for resources: polling using Fetch
    60  	Rest = "rest"
    61  )
    62  
    63  var (
    64  	// RefreshDelay for the polling config source
    65  	RefreshDelay = 500 * time.Millisecond
    66  )
    67  
    68  // MakeEndpoint creates a localhost endpoint on a given port.
    69  func MakeEndpoint(clusterName string, port uint32) *endpoint.ClusterLoadAssignment {
    70  	return &endpoint.ClusterLoadAssignment{
    71  		ClusterName: clusterName,
    72  		Endpoints: []*endpointv2.LocalityLbEndpoints{{
    73  			LbEndpoints: []*endpointv2.LbEndpoint{{
    74  				HostIdentifier: &endpointv2.LbEndpoint_Endpoint{
    75  					Endpoint: &endpointv2.Endpoint{
    76  						Address: &core.Address{
    77  							Address: &core.Address_SocketAddress{
    78  								SocketAddress: &core.SocketAddress{
    79  									Protocol: core.SocketAddress_TCP,
    80  									Address:  localhost,
    81  									PortSpecifier: &core.SocketAddress_PortValue{
    82  										PortValue: port,
    83  									},
    84  								},
    85  							},
    86  						},
    87  					},
    88  				},
    89  			}},
    90  		}},
    91  	}
    92  }
    93  
    94  // MakeCluster creates a cluster using either ADS or EDS.
    95  func MakeCluster(mode string, clusterName string) *cluster.Cluster {
    96  	edsSource := configSource(mode)
    97  
    98  	connectTimeout := 5 * time.Second
    99  	return &cluster.Cluster{
   100  		Name:                 clusterName,
   101  		ConnectTimeout:       ptypes.DurationProto(connectTimeout),
   102  		ClusterDiscoveryType: &cluster.Cluster_Type{Type: cluster.Cluster_EDS},
   103  		EdsClusterConfig: &cluster.Cluster_EdsClusterConfig{
   104  			EdsConfig: edsSource,
   105  		},
   106  	}
   107  }
   108  
   109  // MakeRoute creates an HTTP route that routes to a given cluster.
   110  func MakeRoute(routeName, clusterName string) *route.RouteConfiguration {
   111  	return &route.RouteConfiguration{
   112  		Name: routeName,
   113  		VirtualHosts: []*routev2.VirtualHost{{
   114  			Name:    routeName,
   115  			Domains: []string{"*"},
   116  			Routes: []*routev2.Route{{
   117  				Match: &routev2.RouteMatch{
   118  					PathSpecifier: &routev2.RouteMatch_Prefix{
   119  						Prefix: "/",
   120  					},
   121  				},
   122  				Action: &routev2.Route_Route{
   123  					Route: &routev2.RouteAction{
   124  						ClusterSpecifier: &routev2.RouteAction_Cluster{
   125  							Cluster: clusterName,
   126  						},
   127  					},
   128  				},
   129  			}},
   130  		}},
   131  	}
   132  }
   133  
   134  // data source configuration
   135  func configSource(mode string) *core.ConfigSource {
   136  	source := &core.ConfigSource{}
   137  	source.ResourceApiVersion = resource.DefaultAPIVersion
   138  	switch mode {
   139  	case Ads:
   140  		source.ConfigSourceSpecifier = &core.ConfigSource_Ads{
   141  			Ads: &core.AggregatedConfigSource{},
   142  		}
   143  	case Xds:
   144  		source.ConfigSourceSpecifier = &core.ConfigSource_ApiConfigSource{
   145  			ApiConfigSource: &core.ApiConfigSource{
   146  				TransportApiVersion:       resource.DefaultAPIVersion,
   147  				ApiType:                   core.ApiConfigSource_GRPC,
   148  				SetNodeOnFirstMessageOnly: true,
   149  				GrpcServices: []*core.GrpcService{{
   150  					TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
   151  						EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: XdsCluster},
   152  					},
   153  				}},
   154  			},
   155  		}
   156  	case Rest:
   157  		source.ConfigSourceSpecifier = &core.ConfigSource_ApiConfigSource{
   158  			ApiConfigSource: &core.ApiConfigSource{
   159  				ApiType:             core.ApiConfigSource_REST,
   160  				TransportApiVersion: resource.DefaultAPIVersion,
   161  				ClusterNames:        []string{XdsCluster},
   162  				RefreshDelay:        ptypes.DurationProto(RefreshDelay),
   163  			},
   164  		}
   165  	}
   166  	return source
   167  }
   168  
   169  // MakeHTTPListener creates a listener using either ADS or RDS for the route.
   170  func MakeHTTPListener(mode string, listenerName string, port uint32, route string) *listener.Listener {
   171  	rdsSource := configSource(mode)
   172  
   173  	// access log service configuration
   174  	alsConfig := &als.HttpGrpcAccessLogConfig{
   175  		CommonConfig: &als.CommonGrpcAccessLogConfig{
   176  			LogName: "echo",
   177  			GrpcService: &core.GrpcService{
   178  				TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
   179  					EnvoyGrpc: &core.GrpcService_EnvoyGrpc{
   180  						ClusterName: XdsCluster,
   181  					},
   182  				},
   183  			},
   184  		},
   185  	}
   186  	alsConfigPbst, err := ptypes.MarshalAny(alsConfig)
   187  	if err != nil {
   188  		panic(err)
   189  	}
   190  
   191  	// HTTP filter configuration
   192  	manager := &hcm.HttpConnectionManager{
   193  		CodecType:  hcm.HttpConnectionManager_AUTO,
   194  		StatPrefix: "http",
   195  		RouteSpecifier: &hcm.HttpConnectionManager_Rds{
   196  			Rds: &hcm.Rds{
   197  				ConfigSource:    rdsSource,
   198  				RouteConfigName: route,
   199  			},
   200  		},
   201  		HttpFilters: []*hcm.HttpFilter{{
   202  			Name: wellknown.Router,
   203  		}},
   204  		AccessLog: []*alf.AccessLog{{
   205  			Name: wellknown.HTTPGRPCAccessLog,
   206  			ConfigType: &alf.AccessLog_TypedConfig{
   207  				TypedConfig: alsConfigPbst,
   208  			},
   209  		}},
   210  	}
   211  	pbst, err := ptypes.MarshalAny(manager)
   212  	if err != nil {
   213  		panic(err)
   214  	}
   215  
   216  	return &listener.Listener{
   217  		Name: listenerName,
   218  		Address: &core.Address{
   219  			Address: &core.Address_SocketAddress{
   220  				SocketAddress: &core.SocketAddress{
   221  					Protocol: core.SocketAddress_TCP,
   222  					Address:  localhost,
   223  					PortSpecifier: &core.SocketAddress_PortValue{
   224  						PortValue: port,
   225  					},
   226  				},
   227  			},
   228  		},
   229  		FilterChains: []*listenerv2.FilterChain{{
   230  			Filters: []*listenerv2.Filter{{
   231  				Name: wellknown.HTTPConnectionManager,
   232  				ConfigType: &listenerv2.Filter_TypedConfig{
   233  					TypedConfig: pbst,
   234  				},
   235  			}},
   236  		}},
   237  	}
   238  }
   239  
   240  // MakeTCPListener creates a TCP listener for a cluster.
   241  func MakeTCPListener(listenerName string, port uint32, clusterName string) *listener.Listener {
   242  	// TCP filter configuration
   243  	config := &tcp.TcpProxy{
   244  		StatPrefix: "tcp",
   245  		ClusterSpecifier: &tcp.TcpProxy_Cluster{
   246  			Cluster: clusterName,
   247  		},
   248  	}
   249  	pbst, err := ptypes.MarshalAny(config)
   250  	if err != nil {
   251  		panic(err)
   252  	}
   253  	return &listener.Listener{
   254  		Name: listenerName,
   255  		Address: &core.Address{
   256  			Address: &core.Address_SocketAddress{
   257  				SocketAddress: &core.SocketAddress{
   258  					Protocol: core.SocketAddress_TCP,
   259  					Address:  localhost,
   260  					PortSpecifier: &core.SocketAddress_PortValue{
   261  						PortValue: port,
   262  					},
   263  				},
   264  			},
   265  		},
   266  		FilterChains: []*listenerv2.FilterChain{{
   267  			Filters: []*listenerv2.Filter{{
   268  				Name: wellknown.TCPProxy,
   269  				ConfigType: &listenerv2.Filter_TypedConfig{
   270  					TypedConfig: pbst,
   271  				},
   272  			}},
   273  		}},
   274  	}
   275  }
   276  
   277  // MakeRuntime creates an RTDS layer with some fields.
   278  func MakeRuntime(runtimeName string) *runtime.Runtime {
   279  	return &runtime.Runtime{
   280  		Name: runtimeName,
   281  		Layer: &pstruct.Struct{
   282  			Fields: map[string]*pstruct.Value{
   283  				"field-0": {
   284  					Kind: &pstruct.Value_NumberValue{NumberValue: 100},
   285  				},
   286  				"field-1": {
   287  					Kind: &pstruct.Value_StringValue{StringValue: "foobar"},
   288  				},
   289  			},
   290  		},
   291  	}
   292  }
   293  
   294  // TestSnapshot holds parameters for a synthetic snapshot.
   295  type TestSnapshot struct {
   296  	// Xds indicates snapshot mode: ads, xds, or rest
   297  	Xds string
   298  	// Version for the snapshot.
   299  	Version string
   300  	// UpstreamPort for the single endpoint on the localhost.
   301  	UpstreamPort uint32
   302  	// BasePort is the initial port for the listeners.
   303  	BasePort uint32
   304  	// NumClusters is the total number of clusters to generate.
   305  	NumClusters int
   306  	// NumHTTPListeners is the total number of HTTP listeners to generate.
   307  	NumHTTPListeners int
   308  	// NumTCPListeners is the total number of TCP listeners to generate.
   309  	// Listeners are assigned clusters in a round-robin fashion.
   310  	NumTCPListeners int
   311  	// NumRuntimes is the total number of RTDS layers to generate.
   312  	NumRuntimes int
   313  	// TLS enables SDS-enabled TLS mode on all listeners
   314  	TLS bool
   315  }
   316  
   317  // Generate produces a snapshot from the parameters.
   318  func (ts TestSnapshot) Generate() cache.Snapshot {
   319  	clusters := make([]types.Resource, ts.NumClusters)
   320  	endpoints := make([]types.Resource, ts.NumClusters)
   321  	for i := 0; i < ts.NumClusters; i++ {
   322  		name := fmt.Sprintf("cluster-%s-%d", ts.Version, i)
   323  		clusters[i] = MakeCluster(ts.Xds, name)
   324  		endpoints[i] = MakeEndpoint(name, ts.UpstreamPort)
   325  	}
   326  
   327  	routes := make([]types.Resource, ts.NumHTTPListeners)
   328  	for i := 0; i < ts.NumHTTPListeners; i++ {
   329  		name := fmt.Sprintf("route-%s-%d", ts.Version, i)
   330  		routes[i] = MakeRoute(name, cache.GetResourceName(clusters[i%ts.NumClusters]))
   331  	}
   332  
   333  	total := ts.NumHTTPListeners + ts.NumTCPListeners
   334  	listeners := make([]types.Resource, total)
   335  	for i := 0; i < total; i++ {
   336  		port := ts.BasePort + uint32(i)
   337  		// listener name must be same since ports are shared and previous listener is drained
   338  		name := fmt.Sprintf("listener-%d", port)
   339  		var listener *listener.Listener
   340  		if i < ts.NumHTTPListeners {
   341  			listener = MakeHTTPListener(ts.Xds, name, port, cache.GetResourceName(routes[i]))
   342  		} else {
   343  			listener = MakeTCPListener(name, port, cache.GetResourceName(clusters[i%ts.NumClusters]))
   344  		}
   345  
   346  		if ts.TLS {
   347  			for i, chain := range listener.FilterChains {
   348  				tlsc := &auth.DownstreamTlsContext{
   349  					CommonTlsContext: &auth.CommonTlsContext{
   350  						TlsCertificateSdsSecretConfigs: []*auth.SdsSecretConfig{{
   351  							Name:      tlsName,
   352  							SdsConfig: configSource(ts.Xds),
   353  						}},
   354  						ValidationContextType: &auth.CommonTlsContext_ValidationContextSdsSecretConfig{
   355  							ValidationContextSdsSecretConfig: &auth.SdsSecretConfig{
   356  								Name:      rootName,
   357  								SdsConfig: configSource(ts.Xds),
   358  							},
   359  						},
   360  					},
   361  				}
   362  				mt, _ := ptypes.MarshalAny(tlsc)
   363  				chain.TransportSocket = &core.TransportSocket{
   364  					Name: "envoy.transport_sockets.tls",
   365  					ConfigType: &core.TransportSocket_TypedConfig{
   366  						TypedConfig: mt,
   367  					},
   368  				}
   369  				listener.FilterChains[i] = chain
   370  			}
   371  		}
   372  
   373  		listeners[i] = listener
   374  	}
   375  
   376  	runtimes := make([]types.Resource, ts.NumRuntimes)
   377  	for i := 0; i < ts.NumRuntimes; i++ {
   378  		name := fmt.Sprintf("runtime-%d", i)
   379  		runtimes[i] = MakeRuntime(name)
   380  	}
   381  
   382  	var secrets []types.Resource
   383  	if ts.TLS {
   384  		for _, s := range MakeSecrets(tlsName, rootName) {
   385  			secrets = append(secrets, s)
   386  		}
   387  	}
   388  
   389  	out := cache.NewSnapshot(
   390  		ts.Version,
   391  		endpoints,
   392  		clusters,
   393  		routes,
   394  		listeners,
   395  		runtimes,
   396  		secrets,
   397  	)
   398  
   399  	return out
   400  }
   401  

View as plain text