diff --git a/.changelog/18813.txt b/.changelog/18813.txt new file mode 100644 index 000000000000..3dcb4612915b --- /dev/null +++ b/.changelog/18813.txt @@ -0,0 +1,3 @@ +```release-note:improvement +acl: Use templated policy to generate synthetic policies for tokens/roles with node and/or service identities +``` \ No newline at end of file diff --git a/.changelog/18816.txt b/.changelog/18816.txt new file mode 100644 index 000000000000..ef8989ee705b --- /dev/null +++ b/.changelog/18816.txt @@ -0,0 +1,3 @@ +```release-note:feature +cli: Add `consul acl templated-policy` commands to read, list and preview templated policies. +``` \ No newline at end of file diff --git a/agent/acl_endpoint.go b/agent/acl_endpoint.go index b98784e346ac..fb94862800eb 100644 --- a/agent/acl_endpoint.go +++ b/agent/acl_endpoint.go @@ -1134,12 +1134,6 @@ func (s *HTTPHandlers) ACLAuthorize(resp http.ResponseWriter, req *http.Request) return responses, nil } -type ACLTemplatedPolicyResponse struct { - TemplateName string - Schema string - Template string -} - func (s *HTTPHandlers) ACLTemplatedPoliciesList(resp http.ResponseWriter, req *http.Request) (interface{}, error) { if s.checkACLDisabled() { return nil, aclDisabled @@ -1165,10 +1159,10 @@ func (s *HTTPHandlers) ACLTemplatedPoliciesList(resp http.ResponseWriter, req *h return nil, err } - templatedPolicies := make(map[string]ACLTemplatedPolicyResponse) + templatedPolicies := make(map[string]api.ACLTemplatedPolicyResponse) for tp, tmpBase := range structs.GetACLTemplatedPolicyList() { - templatedPolicies[tp] = ACLTemplatedPolicyResponse{ + templatedPolicies[tp] = api.ACLTemplatedPolicyResponse{ TemplateName: tmpBase.TemplateName, Schema: tmpBase.Schema, Template: tmpBase.Template, @@ -1213,7 +1207,7 @@ func (s *HTTPHandlers) ACLTemplatedPolicyRead(resp http.ResponseWriter, req *htt return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: fmt.Sprintf("Invalid templated policy Name: %s", templateName)} } - return ACLTemplatedPolicyResponse{ + return api.ACLTemplatedPolicyResponse{ TemplateName: baseTemplate.TemplateName, Schema: baseTemplate.Schema, Template: baseTemplate.Template, diff --git a/agent/acl_endpoint_test.go b/agent/acl_endpoint_test.go index 0a135f38dfce..50b2ad20d445 100644 --- a/agent/acl_endpoint_test.go +++ b/agent/acl_endpoint_test.go @@ -1372,11 +1372,11 @@ func TestACL_HTTP(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) - var list map[string]ACLTemplatedPolicyResponse + var list map[string]api.ACLTemplatedPolicyResponse require.NoError(t, json.NewDecoder(resp.Body).Decode(&list)) require.Len(t, list, 3) - require.Equal(t, ACLTemplatedPolicyResponse{ + require.Equal(t, api.ACLTemplatedPolicyResponse{ TemplateName: api.ACLTemplatedPolicyServiceName, Schema: structs.ACLTemplatedPolicyIdentitiesSchema, Template: structs.ACLTemplatedPolicyService, @@ -1399,7 +1399,7 @@ func TestACL_HTTP(t *testing.T) { a.srv.h.ServeHTTP(resp, req) require.Equal(t, http.StatusOK, resp.Code) - var templatedPolicy ACLTemplatedPolicyResponse + var templatedPolicy api.ACLTemplatedPolicyResponse require.NoError(t, json.NewDecoder(resp.Body).Decode(&templatedPolicy)) require.Equal(t, structs.ACLTemplatedPolicyDNSSchema, templatedPolicy.Schema) require.Equal(t, api.ACLTemplatedPolicyDNSName, templatedPolicy.TemplateName) diff --git a/agent/agent_test.go b/agent/agent_test.go index f3932c792d40..455a8bbb3e66 100644 --- a/agent/agent_test.go +++ b/agent/agent_test.go @@ -354,10 +354,10 @@ func TestAgent_HTTPMaxHeaderBytes(t *testing.T) { require.NoError(t, err) a, err := New(bd) + require.NoError(t, err) mockDelegate := delegateMock{} mockDelegate.On("LicenseCheck").Return() a.delegate = &mockDelegate - require.NoError(t, err) a.startLicenseManager(testutil.TestContext(t)) @@ -392,6 +392,8 @@ func TestAgent_HTTPMaxHeaderBytes(t *testing.T) { resp, err := client.Do(req.WithContext(ctx)) require.NoError(t, err) require.Equal(t, tt.expectedHTTPResponse, resp.StatusCode, "expected a '%d' http response, got '%d'", tt.expectedHTTPResponse, resp.StatusCode) + resp.Body.Close() + s.Shutdown(ctx) } }) } diff --git a/agent/consul/type_registry.go b/agent/consul/type_registry.go index 90bf76576fcf..a23f72b9b23e 100644 --- a/agent/consul/type_registry.go +++ b/agent/consul/type_registry.go @@ -4,6 +4,7 @@ package consul import ( + "github.com/hashicorp/consul/internal/auth" "github.com/hashicorp/consul/internal/catalog" "github.com/hashicorp/consul/internal/mesh" "github.com/hashicorp/consul/internal/resource" @@ -23,6 +24,7 @@ func NewTypeRegistry() resource.Registry { demo.RegisterTypes(registry) mesh.RegisterTypes(registry) catalog.RegisterTypes(registry) + auth.RegisterTypes(registry) return registry } diff --git a/agent/hcp/telemetry/otel_sink_test.go b/agent/hcp/telemetry/otel_sink_test.go index 30bbeee519b7..683f33a3a40d 100644 --- a/agent/hcp/telemetry/otel_sink_test.go +++ b/agent/hcp/telemetry/otel_sink_test.go @@ -334,7 +334,7 @@ func TestLabelsToAttributes(t *testing.T) { sink, err := NewOTELSink(ctx, opts) require.NoError(t, err) - require.Equal(t, test.expectedOTELAttributes, sink.labelsToAttributes(test.goMetricsLabels)) + require.ElementsMatch(t, test.expectedOTELAttributes, sink.labelsToAttributes(test.goMetricsLabels)) }) } } diff --git a/agent/structs/acl.go b/agent/structs/acl.go index 50211b7c7412..4d76dffa4e8e 100644 --- a/agent/structs/acl.go +++ b/agent/structs/acl.go @@ -9,11 +9,11 @@ import ( "errors" "fmt" "hash" - "hash/fnv" "sort" "strings" "time" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/lib/stringslice" "golang.org/x/crypto/blake2b" @@ -182,22 +182,20 @@ func (s *ACLServiceIdentity) EstimateSize() int { } func (s *ACLServiceIdentity) SyntheticPolicy(entMeta *acl.EnterpriseMeta) *ACLPolicy { + // use templated policy to generate synthetic policy + templatedPolicy := ACLTemplatedPolicy{ + TemplateID: ACLTemplatedPolicyServiceID, + TemplateName: api.ACLTemplatedPolicyServiceName, + Datacenters: s.Datacenters, + TemplateVariables: &ACLTemplatedPolicyVariables{ + Name: s.ServiceName, + }, + } + // Given that we validate this string name before persisting, we do not - // have to escape it before doing the following interpolation. - rules := aclServiceIdentityRules(s.ServiceName, entMeta) - - hasher := fnv.New128a() - hashID := fmt.Sprintf("%x", hasher.Sum([]byte(rules))) - - policy := &ACLPolicy{} - policy.ID = hashID - policy.Name = fmt.Sprintf("synthetic-policy-%s", hashID) - sn := NewServiceName(s.ServiceName, entMeta) - policy.Description = fmt.Sprintf("synthetic policy for service identity %q", sn.String()) - policy.Rules = rules - policy.Datacenters = s.Datacenters - policy.EnterpriseMeta.Merge(entMeta) - policy.SetHash(true) + // expect any errors from generating the synthetic policy + policy, _ := templatedPolicy.SyntheticPolicy(entMeta) + return policy } @@ -254,21 +252,20 @@ func (s *ACLNodeIdentity) EstimateSize() int { } func (s *ACLNodeIdentity) SyntheticPolicy(entMeta *acl.EnterpriseMeta) *ACLPolicy { + // use templated policy to generate synthetic policy + templatedPolicy := ACLTemplatedPolicy{ + TemplateID: ACLTemplatedPolicyNodeID, + TemplateName: api.ACLTemplatedPolicyNodeName, + Datacenters: []string{s.Datacenter}, + TemplateVariables: &ACLTemplatedPolicyVariables{ + Name: s.NodeName, + }, + } + // Given that we validate this string name before persisting, we do not - // have to escape it before doing the following interpolation. - rules := aclNodeIdentityRules(s.NodeName, entMeta) - - hasher := fnv.New128a() - hashID := fmt.Sprintf("%x", hasher.Sum([]byte(rules))) - - policy := &ACLPolicy{} - policy.ID = hashID - policy.Name = fmt.Sprintf("synthetic-policy-%s", hashID) - policy.Description = fmt.Sprintf("synthetic policy for node identity %q", s.NodeName) - policy.Rules = rules - policy.Datacenters = []string{s.Datacenter} - policy.EnterpriseMeta.Merge(entMeta) - policy.SetHash(true) + // expect any errors from generating the synthetic policy + policy, _ := templatedPolicy.SyntheticPolicy(entMeta) + return policy } diff --git a/agent/structs/acl_templated_policy.go b/agent/structs/acl_templated_policy.go index 4e6fab577888..1e62c984ce29 100644 --- a/agent/structs/acl_templated_policy.go +++ b/agent/structs/acl_templated_policy.go @@ -23,19 +23,20 @@ type ACLTemplatedPolicies []*ACLTemplatedPolicy const ( ACLTemplatedPolicyNodeID = "00000000-0000-0000-0000-000000000004" ACLTemplatedPolicyServiceID = "00000000-0000-0000-0000-000000000003" - ACLTemplatedPolicyIdentitiesSchema = `{ - "type": "object", - "properties": { - "name": { "type": "string", "$ref": "#/definitions/min-length-one" } - }, - "required": ["name"], - "definitions": { - "min-length-one": { - "type": "string", - "minLength": 1 - } + ACLTemplatedPolicyIdentitiesSchema = ` +{ + "type": "object", + "properties": { + "name": { "type": "string", "$ref": "#/definitions/min-length-one" } + }, + "required": ["name"], + "definitions": { + "min-length-one": { + "type": "string", + "minLength": 1 } - }` + } +}` ACLTemplatedPolicyDNSID = "00000000-0000-0000-0000-000000000005" ACLTemplatedPolicyDNSSchema = "" // empty schema as it does not require variables @@ -51,8 +52,9 @@ type ACLTemplatedPolicyBase struct { } var ( - // TODO(Ronald): add other templates // This supports: node, service and dns templates + // Note: when adding a new builtin template, ensure you update `command/acl/templatedpolicy/formatter.go` + // to handle the new templates required variables and schema. aclTemplatedPoliciesList = map[string]*ACLTemplatedPolicyBase{ api.ACLTemplatedPolicyServiceName: { TemplateID: ACLTemplatedPolicyServiceID, diff --git a/agent/xds/proxystateconverter/listeners.go b/agent/xds/proxystateconverter/listeners.go index 433bf815356f..0d74a709c193 100644 --- a/agent/xds/proxystateconverter/listeners.go +++ b/agent/xds/proxystateconverter/listeners.go @@ -14,9 +14,8 @@ import ( "time" envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" - "github.com/hashicorp/go-uuid" - "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-uuid" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/wrapperspb" @@ -1443,7 +1442,11 @@ func makeL4Destination(opts destinationOpts) (*pbproxystate.L4Destination, error l4Dest := &pbproxystate.L4Destination{ //AccessLog: accessLogs, - Name: opts.cluster, + Destination: &pbproxystate.L4Destination_Cluster{ + Cluster: &pbproxystate.DestinationCluster{ + Name: opts.cluster, + }, + }, StatPrefix: makeStatPrefix(opts.statPrefix, opts.filterName), } return l4Dest, nil diff --git a/agent/xdsv2/cluster_resources.go b/agent/xdsv2/cluster_resources.go index 5eedd1f21f37..99209d0c343c 100644 --- a/agent/xdsv2/cluster_resources.go +++ b/agent/xdsv2/cluster_resources.go @@ -12,11 +12,11 @@ import ( envoy_aggregate_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/clusters/aggregate/v3" envoy_upstreams_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/v3" envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" ) func (pr *ProxyResources) doesEnvoyClusterAlreadyExist(name string) bool { @@ -174,9 +174,11 @@ func (pr *ProxyResources) makeEnvoyStaticCluster(name string, protocol string, s } return cluster, nil } + func (pr *ProxyResources) makeEnvoyDnsCluster(name string, protocol string, dns *pbproxystate.DNSEndpointGroup) (*envoy_cluster_v3.Cluster, error) { return nil, nil } + func (pr *ProxyResources) makeEnvoyPassthroughCluster(name string, protocol string, passthrough *pbproxystate.PassthroughEndpointGroup) (*envoy_cluster_v3.Cluster, error) { cluster := &envoy_cluster_v3.Cluster{ Name: name, @@ -343,6 +345,6 @@ func addEnvoyLBToCluster(dynamicConfig *pbproxystate.DynamicEndpointGroupConfig, } // TODO(proxystate): In a future PR this will create clusters and add it to ProxyResources.proxyState -func (pr *ProxyResources) makeEnvoyClusterFromL4Destination(name string) error { +func (pr *ProxyResources) makeEnvoyClusterFromL4Destination(l4 *pbproxystate.L4Destination) error { return nil } diff --git a/agent/xdsv2/listener_resources.go b/agent/xdsv2/listener_resources.go index 3517572ce8cc..ca8a3fa3b31b 100644 --- a/agent/xdsv2/listener_resources.go +++ b/agent/xdsv2/listener_resources.go @@ -304,7 +304,7 @@ func (pr *ProxyResources) makeEnvoyResourcesForSNIDestination(sni *pbproxystate. } func (pr *ProxyResources) makeEnvoyResourcesForL4Destination(l4 *pbproxystate.Router_L4) ([]*envoy_listener_v3.Filter, error) { - err := pr.makeEnvoyClusterFromL4Destination(l4.L4.Name) + err := pr.makeEnvoyClusterFromL4Destination(l4.L4) if err != nil { return nil, err } @@ -355,9 +355,30 @@ func makeL4Filters(defaultAllow bool, l4 *pbproxystate.L4Destination) ([]*envoy_ // Add tcp proxy filter tcp := &envoy_tcp_proxy_v3.TcpProxy{ - ClusterSpecifier: &envoy_tcp_proxy_v3.TcpProxy_Cluster{Cluster: l4.Name}, - StatPrefix: l4.StatPrefix, + StatPrefix: l4.StatPrefix, + } + + switch dest := l4.Destination.(type) { + case *pbproxystate.L4Destination_Cluster: + tcp.ClusterSpecifier = &envoy_tcp_proxy_v3.TcpProxy_Cluster{Cluster: dest.Cluster.Name} + case *pbproxystate.L4Destination_WeightedClusters: + clusters := make([]*envoy_tcp_proxy_v3.TcpProxy_WeightedCluster_ClusterWeight, 0, len(dest.WeightedClusters.Clusters)) + for _, cluster := range dest.WeightedClusters.Clusters { + clusters = append(clusters, &envoy_tcp_proxy_v3.TcpProxy_WeightedCluster_ClusterWeight{ + Name: cluster.Name, + Weight: cluster.Weight.GetValue(), + }) + } + + tcp.ClusterSpecifier = &envoy_tcp_proxy_v3.TcpProxy_WeightedClusters{ + WeightedClusters: &envoy_tcp_proxy_v3.TcpProxy_WeightedCluster{ + Clusters: clusters, + }, + } + default: + return nil, fmt.Errorf("unexpected l4 destination type: %T", l4.Destination) } + tcpFilter, err := makeEnvoyFilter(envoyNetworkFilterName, tcp) if err != nil { return nil, err diff --git a/agent/xdsv2/testdata/input/l4-single-implicit-destination-tproxy.golden b/agent/xdsv2/testdata/input/l4-single-implicit-destination-tproxy.golden index 8d0714e86ca0..f17fbfac21c2 100644 --- a/agent/xdsv2/testdata/input/l4-single-implicit-destination-tproxy.golden +++ b/agent/xdsv2/testdata/input/l4-single-implicit-destination-tproxy.golden @@ -1,59 +1,61 @@ { - "proxyState": { - "identity": { - "tenancy": { - "partition": "default", - "namespace": "default", - "peerName": "local" + "proxyState": { + "identity": { + "tenancy": { + "partition": "default", + "namespace": "default", + "peerName": "local" }, - "name": "test-identity" + "name": "test-identity" }, - "listeners": [ + "listeners": [ { - "name": "outbound_listener", - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "127.0.0.1", - "port": 15001 + "name": "outbound_listener", + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "127.0.0.1", + "port": 15001 }, - "routers": [ + "routers": [ { - "match": { - "prefixRanges": [ + "match": { + "prefixRanges": [ { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 + "addressPrefix": "1.1.1.1", + "prefixLen": 32 } ], "destinationPort": 8080 }, - "l4": { - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "statPrefix": "upstream.tcp.api-1.default.default.dc1" + "l4": { + "cluster": { + "name": "tcp.api-1.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-1.default.default.dc1" } } ], - "capabilities": [ + "capabilities": [ "CAPABILITY_TRANSPARENT" ] } ], - "clusters": { - "tcp.api-1.default.dc1.internal.foo.consul": { - "endpointGroup": { - "dynamic": { - "config": { - "disablePanicThreshold": true + "clusters": { + "tcp.api-1.default.dc1.internal.foo.consul": { + "endpointGroup": { + "dynamic": { + "config": { + "disablePanicThreshold": true }, - "outboundTls": { - "outboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "spiffeIds": [ + "outboundTls": { + "outboundMesh": { + "identityKey": "test-identity", + "validationContext": { + "spiffeIds": [ "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" ] }, - "sni": "api-1.default.dc1.internal.foo.consul" + "sni": "api-1.default.dc1.internal.foo.consul" }, "alpnProtocols": [ "consul~tcp" @@ -64,22 +66,22 @@ } } }, - "requiredEndpoints": { - "api-1.default.dc1.internal.foo.consul": { - "id": { - "name": "api-1", - "type": { - "group": "catalog", - "groupVersion": "v1alpha1", - "kind": "ServiceEndpoints" + "requiredEndpoints": { + "api-1.default.dc1.internal.foo.consul": { + "id": { + "name": "api-1", + "type": { + "group": "catalog", + "groupVersion": "v1alpha1", + "kind": "ServiceEndpoints" }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peerName": "local" + "tenancy": { + "partition": "default", + "namespace": "default", + "peerName": "local" } }, - "port": "mesh" + "port": "mesh" } } } \ No newline at end of file diff --git a/api/acl.go b/api/acl.go index 31130cafc325..68d6f1f54cec 100644 --- a/api/acl.go +++ b/api/acl.go @@ -166,6 +166,12 @@ type ACLTemplatedPolicy struct { Datacenters []string `json:",omitempty"` } +type ACLTemplatedPolicyResponse struct { + TemplateName string + Schema string + Template string +} + type ACLTemplatedPolicyVariables struct { Name string } @@ -1653,3 +1659,78 @@ func (a *ACL) OIDCCallback(auth *ACLOIDCCallbackParams, q *WriteOptions) (*ACLTo } return &out, wm, nil } + +// TemplatedPolicyReadByName retrieves the templated policy details (by name). Returns nil if not found. +func (a *ACL) TemplatedPolicyReadByName(templateName string, q *QueryOptions) (*ACLTemplatedPolicyResponse, *QueryMeta, error) { + r := a.c.newRequest("GET", "/v1/acl/templated-policy/name/"+templateName) + r.setQueryOptions(q) + rtt, resp, err := a.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + found, resp, err := requireNotFoundOrOK(resp) + if err != nil { + return nil, nil, err + } + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + if !found { + return nil, qm, nil + } + + var out ACLTemplatedPolicyResponse + if err := decodeBody(resp, &out); err != nil { + return nil, nil, err + } + + return &out, qm, nil +} + +// TemplatedPolicyList retrieves a listing of all templated policies. +func (a *ACL) TemplatedPolicyList(q *QueryOptions) (map[string]ACLTemplatedPolicyResponse, *QueryMeta, error) { + r := a.c.newRequest("GET", "/v1/acl/templated-policies") + r.setQueryOptions(q) + rtt, resp, err := a.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var entries map[string]ACLTemplatedPolicyResponse + if err := decodeBody(resp, &entries); err != nil { + return nil, nil, err + } + return entries, qm, nil +} + +// TemplatedPolicyPreview is used to preview the policy rendered by the templated policy. +func (a *ACL) TemplatedPolicyPreview(tp *ACLTemplatedPolicy, q *WriteOptions) (*ACLPolicy, *WriteMeta, error) { + r := a.c.newRequest("POST", "/v1/acl/templated-policy/preview/"+tp.TemplateName) + r.setWriteOptions(q) + r.obj = tp.TemplateVariables + + rtt, resp, err := a.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } + wm := &WriteMeta{RequestTime: rtt} + var out ACLPolicy + if err := decodeBody(resp, &out); err != nil { + return nil, nil, err + } + return &out, wm, nil +} diff --git a/command/acl/templatedpolicy/formatter.go b/command/acl/templatedpolicy/formatter.go new file mode 100644 index 000000000000..a3b18fddf7ae --- /dev/null +++ b/command/acl/templatedpolicy/formatter.go @@ -0,0 +1,132 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package templatedpolicy + +import ( + "bytes" + "encoding/json" + "fmt" + "sort" + + "github.com/hashicorp/consul/api" +) + +const ( + PrettyFormat string = "pretty" + JSONFormat string = "json" + WhitespaceIndent = "\t" +) + +// Formatter defines methods provided by templated-policy command output formatter +type Formatter interface { + FormatTemplatedPolicy(policy api.ACLTemplatedPolicyResponse) (string, error) + FormatTemplatedPolicyList(policies map[string]api.ACLTemplatedPolicyResponse) (string, error) +} + +// GetSupportedFormats returns supported formats +func GetSupportedFormats() []string { + return []string{PrettyFormat, JSONFormat} +} + +// NewFormatter returns Formatter implementation +func NewFormatter(format string, showMeta bool) (formatter Formatter, err error) { + switch format { + case PrettyFormat: + formatter = newPrettyFormatter(showMeta) + case JSONFormat: + formatter = newJSONFormatter(showMeta) + default: + err = fmt.Errorf("unknown format: %q", format) + } + + return formatter, err +} + +func newPrettyFormatter(showMeta bool) Formatter { + return &prettyFormatter{showMeta} +} + +func newJSONFormatter(showMeta bool) Formatter { + return &jsonFormatter{showMeta} +} + +type prettyFormatter struct { + showMeta bool +} + +// FormatTemplatedPolicy displays template name, input variables and example usages. When +// showMeta is true, we display raw template code and schema. +// This implementation is a conscious choice as we know builtin variables we know every required/optional input variables +// so we can just hardcode this. +// In the future, when we implement user defined templated policies, we will move this to some sort of schema parsing. +// This implementation allows us to move forward without limiting ourselves when implementing user defined templated policies. +func (f *prettyFormatter) FormatTemplatedPolicy(templatedPolicy api.ACLTemplatedPolicyResponse) (string, error) { + var buffer bytes.Buffer + + buffer.WriteString(fmt.Sprintf("Name: %s\n", templatedPolicy.TemplateName)) + + buffer.WriteString("Input variables:") + switch templatedPolicy.TemplateName { + case api.ACLTemplatedPolicyServiceName: + buffer.WriteString(fmt.Sprintf("\n%sName: String - Required - The name of the service.\n", WhitespaceIndent)) + buffer.WriteString("Example usage:\n") + buffer.WriteString(WhitespaceIndent + "consul acl token create -templated-policy builtin/service -var name:api\n") + case api.ACLTemplatedPolicyNodeName: + buffer.WriteString(fmt.Sprintf("\n%sName: String - Required - The node name.\n", WhitespaceIndent)) + buffer.WriteString("Example usage:\n") + buffer.WriteString(fmt.Sprintf("%sconsul acl token create -templated-policy builtin/node -var name:node-1\n", WhitespaceIndent)) + case api.ACLTemplatedPolicyDNSName: + buffer.WriteString(" None\n") + buffer.WriteString("Example usage:\n") + buffer.WriteString(fmt.Sprintf("%sconsul acl token create -templated-policy builtin/dns\n", WhitespaceIndent)) + default: + buffer.WriteString(" None\n") + } + + if f.showMeta { + if templatedPolicy.Schema != "" { + buffer.WriteString(fmt.Sprintf("Schema:\n%s\n\n", templatedPolicy.Schema)) + } + buffer.WriteString(fmt.Sprintf("Raw Template:\n%s\n", templatedPolicy.Template)) + } + + return buffer.String(), nil +} + +func (f *prettyFormatter) FormatTemplatedPolicyList(policies map[string]api.ACLTemplatedPolicyResponse) (string, error) { + var buffer bytes.Buffer + + templateNames := make([]string, 0, len(policies)) + for _, templatedPolicy := range policies { + templateNames = append(templateNames, templatedPolicy.TemplateName) + } + + //ensure the list is consistently sorted by strings + sort.Strings(templateNames) + for _, name := range templateNames { + buffer.WriteString(fmt.Sprintf("%s\n", name)) + } + + return buffer.String(), nil +} + +type jsonFormatter struct { + showMeta bool +} + +func (f *jsonFormatter) FormatTemplatedPolicy(templatedPolicy api.ACLTemplatedPolicyResponse) (string, error) { + b, err := json.MarshalIndent(templatedPolicy, "", " ") + if err != nil { + return "", fmt.Errorf("failed to marshal templated policy: %v", err) + } + return string(b), nil +} + +func (f *jsonFormatter) FormatTemplatedPolicyList(templatedPolicies map[string]api.ACLTemplatedPolicyResponse) (string, error) { + b, err := json.MarshalIndent(templatedPolicies, "", " ") + if err != nil { + return "", fmt.Errorf("failed to marshal templated policies: %v", err) + } + return string(b), nil +} diff --git a/command/acl/templatedpolicy/formatter_ce_test.go b/command/acl/templatedpolicy/formatter_ce_test.go new file mode 100644 index 000000000000..1d490afeadc6 --- /dev/null +++ b/command/acl/templatedpolicy/formatter_ce_test.go @@ -0,0 +1,17 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +//go:build !consulent +// +build !consulent + +package templatedpolicy + +import "testing" + +func TestFormatTemplatedPolicy(t *testing.T) { + testFormatTemplatedPolicy(t, "FormatTemplatedPolicy/ce") +} + +func TestFormatTemplatedPolicyList(t *testing.T) { + testFormatTemplatedPolicyList(t, "FormatTemplatedPolicyList/ce") +} diff --git a/command/acl/templatedpolicy/formatter_test.go b/command/acl/templatedpolicy/formatter_test.go new file mode 100644 index 000000000000..d6e8fa4d0c20 --- /dev/null +++ b/command/acl/templatedpolicy/formatter_test.go @@ -0,0 +1,118 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package templatedpolicy + +import ( + "fmt" + "os" + "path" + "path/filepath" + "testing" + + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/api" + "github.com/stretchr/testify/require" +) + +// golden reads from the golden file returning the contents as a string. +func golden(t *testing.T, name string) string { + t.Helper() + + golden := filepath.Join("testdata", name+".golden") + expected, err := os.ReadFile(golden) + require.NoError(t, err) + + return string(expected) +} + +func testFormatTemplatedPolicy(t *testing.T, dirPath string) { + type testCase struct { + templatedPolicy api.ACLTemplatedPolicyResponse + } + + cases := map[string]testCase{ + "node-templated-policy": { + templatedPolicy: api.ACLTemplatedPolicyResponse{ + TemplateName: api.ACLTemplatedPolicyNodeName, + Schema: structs.ACLTemplatedPolicyIdentitiesSchema, + Template: structs.ACLTemplatedPolicyNode, + }, + }, + "dns-templated-policy": { + templatedPolicy: api.ACLTemplatedPolicyResponse{ + TemplateName: api.ACLTemplatedPolicyDNSName, + Schema: structs.ACLTemplatedPolicyDNSSchema, + Template: structs.ACLTemplatedPolicyDNS, + }, + }, + "service-templated-policy": { + templatedPolicy: api.ACLTemplatedPolicyResponse{ + TemplateName: api.ACLTemplatedPolicyServiceName, + Schema: structs.ACLTemplatedPolicyIdentitiesSchema, + Template: structs.ACLTemplatedPolicyService, + }, + }, + } + + formatters := map[string]Formatter{ + "pretty": newPrettyFormatter(false), + "pretty-meta": newPrettyFormatter(true), + // the JSON formatter ignores the showMeta + "json": newJSONFormatter(false), + } + + for name, tcase := range cases { + t.Run(name, func(t *testing.T) { + for fmtName, formatter := range formatters { + t.Run(fmtName, func(t *testing.T) { + actual, err := formatter.FormatTemplatedPolicy(tcase.templatedPolicy) + require.NoError(t, err) + + gName := fmt.Sprintf("%s.%s", name, fmtName) + + expected := golden(t, path.Join(dirPath, gName)) + require.Equal(t, expected, actual) + }) + } + }) + } +} + +func testFormatTemplatedPolicyList(t *testing.T, dirPath string) { + // we don't consider the showMeta field for policy list + formatters := map[string]Formatter{ + "pretty": newPrettyFormatter(false), + "json": newJSONFormatter(false), + } + + policies := map[string]api.ACLTemplatedPolicyResponse{ + "builtin/node": { + TemplateName: api.ACLTemplatedPolicyNodeName, + Schema: structs.ACLTemplatedPolicyIdentitiesSchema, + Template: structs.ACLTemplatedPolicyNode, + }, + "builtin/dns": { + TemplateName: api.ACLTemplatedPolicyDNSName, + Schema: structs.ACLTemplatedPolicyDNSSchema, + Template: structs.ACLTemplatedPolicyDNS, + }, + "builtin/service": { + TemplateName: api.ACLTemplatedPolicyServiceName, + Schema: structs.ACLTemplatedPolicyIdentitiesSchema, + Template: structs.ACLTemplatedPolicyService, + }, + } + + for fmtName, formatter := range formatters { + t.Run(fmtName, func(t *testing.T) { + actual, err := formatter.FormatTemplatedPolicyList(policies) + require.NoError(t, err) + + gName := fmt.Sprintf("list.%s", fmtName) + + expected := golden(t, path.Join(dirPath, gName)) + require.Equal(t, expected, actual) + }) + } +} diff --git a/command/acl/templatedpolicy/list/templated_policy_list.go b/command/acl/templatedpolicy/list/templated_policy_list.go new file mode 100644 index 000000000000..3e5e30570f12 --- /dev/null +++ b/command/acl/templatedpolicy/list/templated_policy_list.go @@ -0,0 +1,101 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package templatedpolicylist + +import ( + "flag" + "fmt" + "strings" + + "github.com/mitchellh/cli" + + "github.com/hashicorp/consul/command/acl/templatedpolicy" + "github.com/hashicorp/consul/command/flags" +) + +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.init() + return c +} + +type cmd struct { + UI cli.Ui + flags *flag.FlagSet + http *flags.HTTPFlags + help string + + format string +} + +func (c *cmd) init() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + c.flags.StringVar( + &c.format, + "format", + templatedpolicy.PrettyFormat, + fmt.Sprintf("Output format {%s}", strings.Join(templatedpolicy.GetSupportedFormats(), "|")), + ) + + c.http = &flags.HTTPFlags{} + flags.Merge(c.flags, c.http.ClientFlags()) + flags.Merge(c.flags, c.http.ServerFlags()) + flags.Merge(c.flags, c.http.MultiTenancyFlags()) + c.help = flags.Usage(help, c.flags) +} + +func (c *cmd) Run(args []string) int { + if err := c.flags.Parse(args); err != nil { + return 1 + } + + client, err := c.http.APIClient() + if err != nil { + c.UI.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err)) + return 1 + } + + tps, _, err := client.ACL().TemplatedPolicyList(nil) + if err != nil { + c.UI.Error(fmt.Sprintf("Failed to retrieve the templated policies list: %v", err)) + return 1 + } + + formatter, err := templatedpolicy.NewFormatter(c.format, false) + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + out, err := formatter.FormatTemplatedPolicyList(tps) + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + if out != "" { + c.UI.Info(out) + } + + return 0 +} + +func (c *cmd) Synopsis() string { + return synopsis +} + +func (c *cmd) Help() string { + return flags.Usage(c.help, nil) +} + +const ( + synopsis = "Lists ACL templated policies" + help = ` +Usage: consul acl templated-policy list [options] + + Lists all the ACL templated policies. + + Example: + + $ consul acl templated-policy list +` +) diff --git a/command/acl/templatedpolicy/list/templated_policy_list_test.go b/command/acl/templatedpolicy/list/templated_policy_list_test.go new file mode 100644 index 000000000000..bdde3782d76d --- /dev/null +++ b/command/acl/templatedpolicy/list/templated_policy_list_test.go @@ -0,0 +1,102 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package templatedpolicylist + +import ( + "encoding/json" + "strings" + "testing" + + "github.com/hashicorp/consul/agent" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/testrpc" + "github.com/mitchellh/cli" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestTemplatedPolicyListCommand_noTabs(t *testing.T) { + t.Parallel() + + if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') { + t.Fatal("help has tabs") + } +} + +func TestTemplatedPolicyListCommand(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + a := agent.NewTestAgent(t, ` + primary_datacenter = "dc1" + acl { + enabled = true + tokens { + initial_management = "root" + } + }`) + + defer a.Shutdown() + testrpc.WaitForTestAgent(t, a.RPC, "dc1", testrpc.WithToken("root")) + + ui := cli.NewMockUi() + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-token=root", + } + + cmd := New(ui) + code := cmd.Run(args) + assert.Equal(t, code, 0) + assert.Empty(t, ui.ErrorWriter.String()) + + output := ui.OutputWriter.String() + require.Contains(t, output, api.ACLTemplatedPolicyServiceName) + require.Contains(t, output, api.ACLTemplatedPolicyDNSName) +} + +func TestTemplatedPolicyListCommand_JSON(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + a := agent.NewTestAgent(t, ` + primary_datacenter = "dc1" + acl { + enabled = true + tokens { + initial_management = "root" + } + }`) + + defer a.Shutdown() + testrpc.WaitForTestAgent(t, a.RPC, "dc1", testrpc.WithToken("root")) + + ui := cli.NewMockUi() + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-token=root", + "-format=json", + } + + cmd := New(ui) + code := cmd.Run(args) + assert.Equal(t, code, 0) + assert.Empty(t, ui.ErrorWriter.String()) + output := ui.OutputWriter.String() + require.Contains(t, output, api.ACLTemplatedPolicyServiceName) + require.Contains(t, output, api.ACLTemplatedPolicyDNSName) + + var jsonOutput map[string]api.ACLTemplatedPolicyResponse + err := json.Unmarshal([]byte(output), &jsonOutput) + assert.NoError(t, err) + outputTemplate := jsonOutput[api.ACLTemplatedPolicyDNSName] + assert.Equal(t, structs.ACLTemplatedPolicyDNSSchema, outputTemplate.Schema) +} diff --git a/command/acl/templatedpolicy/preview/templated_policy_preview.go b/command/acl/templatedpolicy/preview/templated_policy_preview.go new file mode 100644 index 000000000000..c2dc706f9007 --- /dev/null +++ b/command/acl/templatedpolicy/preview/templated_policy_preview.go @@ -0,0 +1,134 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package templatedpolicylist + +import ( + "flag" + "fmt" + "strings" + + "github.com/mitchellh/cli" + + "github.com/hashicorp/consul/command/acl" + "github.com/hashicorp/consul/command/acl/policy" + "github.com/hashicorp/consul/command/acl/templatedpolicy" + "github.com/hashicorp/consul/command/flags" +) + +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.init() + return c +} + +type cmd struct { + UI cli.Ui + flags *flag.FlagSet + http *flags.HTTPFlags + help string + + templatedPolicyName string + templatedPolicyFile string + templatedPolicyVariables []string + format string +} + +func (c *cmd) init() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + c.flags.StringVar( + &c.format, + "format", + templatedpolicy.PrettyFormat, + fmt.Sprintf("Output format {%s}", strings.Join(templatedpolicy.GetSupportedFormats(), "|")), + ) + c.flags.Var((*flags.AppendSliceValue)(&c.templatedPolicyVariables), "var", "Templated policy variables."+ + " Must be used in combination with -name flag to specify required variables."+ + " May be specified multiple times with different variables."+ + " Format is VariableName:Value") + c.flags.StringVar(&c.templatedPolicyName, "name", "", "The templated policy name. Use -var flag to specify variables when required.") + c.flags.StringVar(&c.templatedPolicyFile, "file", "", "Path to a file containing templated policies and variables.") + + c.http = &flags.HTTPFlags{} + flags.Merge(c.flags, c.http.ClientFlags()) + flags.Merge(c.flags, c.http.ServerFlags()) + flags.Merge(c.flags, c.http.MultiTenancyFlags()) + c.help = flags.Usage(help, c.flags) +} + +func (c *cmd) Run(args []string) int { + if err := c.flags.Parse(args); err != nil { + return 1 + } + + if len(c.templatedPolicyName) == 0 && len(c.templatedPolicyFile) == 0 { + c.UI.Error("Cannot preview a templated policy without specifying -name or -file") + return 1 + } + + client, err := c.http.APIClient() + if err != nil { + c.UI.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err)) + return 1 + } + + parsedTemplatedPolicies, err := acl.ExtractTemplatedPolicies(c.templatedPolicyName, c.templatedPolicyFile, c.templatedPolicyVariables) + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + + if !(len(parsedTemplatedPolicies) == 1) { + c.UI.Error("Can only preview a single templated policy at a time.") + return 1 + } + + syntheticPolicy, _, err := client.ACL().TemplatedPolicyPreview(parsedTemplatedPolicies[0], nil) + if err != nil { + c.UI.Error(fmt.Sprintf("Failed to generate the templated policy preview: %v", err)) + return 1 + } + + formatter, err := policy.NewFormatter(c.format, false) + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + out, err := formatter.FormatPolicy(syntheticPolicy) + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + if out != "" { + c.UI.Info(out) + } + + return 0 +} + +func (c *cmd) Synopsis() string { + return synopsis +} + +func (c *cmd) Help() string { + return flags.Usage(c.help, nil) +} + +const ( + synopsis = "Preview the policy rendered by the ACL templated policy" + help = ` +Usage: consul acl templated-policy preview [options] + + Preview the policy rendered by the ACL templated policy. + + Example: + + $ consul acl templated-policy preview -name "builtin/service" -var "name:api" + + Preview a templated policy using a file. + + Example: + + $ consul acl templated-policy preview -file templated-policy-file.hcl +` +) diff --git a/command/acl/templatedpolicy/preview/templated_policy_preview_test.go b/command/acl/templatedpolicy/preview/templated_policy_preview_test.go new file mode 100644 index 000000000000..706e1d270f16 --- /dev/null +++ b/command/acl/templatedpolicy/preview/templated_policy_preview_test.go @@ -0,0 +1,204 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package templatedpolicylist + +import ( + "encoding/json" + "os" + "strings" + "testing" + + "github.com/hashicorp/consul/agent" + "github.com/hashicorp/consul/sdk/testutil" + "github.com/hashicorp/consul/testrpc" + "github.com/mitchellh/cli" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestTemplatedPolicyPreviewCommand_noTabs(t *testing.T) { + t.Parallel() + + if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') { + t.Fatal("help has tabs") + } +} + +func TestTemplatedPolicyPreviewCommand(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + testDir := testutil.TempDir(t, "acl") + + a := agent.NewTestAgent(t, ` + primary_datacenter = "dc1" + acl { + enabled = true + tokens { + initial_management = "root" + } + }`) + + defer a.Shutdown() + testrpc.WaitForTestAgent(t, a.RPC, "dc1", testrpc.WithToken("root")) + + t.Run("missing name and file flags", func(t *testing.T) { + ui := cli.NewMockUi() + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-token=root", + } + + cmd := New(ui) + code := cmd.Run(args) + assert.Equal(t, code, 1) + assert.Contains(t, ui.ErrorWriter.String(), "Cannot preview a templated policy without specifying -name or -file") + }) + + t.Run("missing required template variables", func(t *testing.T) { + ui := cli.NewMockUi() + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-token=root", + "-name=builtin/node", + } + + cmd := New(ui) + code := cmd.Run(args) + assert.Equal(t, code, 1) + assert.Contains(t, ui.ErrorWriter.String(), "Failed to generate the templated policy preview") + }) + + t.Run("correct input", func(t *testing.T) { + ui := cli.NewMockUi() + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-token=root", + "-name=builtin/node", + "-var=name:api", + } + + cmd := New(ui) + code := cmd.Run(args) + assert.Equal(t, code, 0) + assert.Empty(t, ui.ErrorWriter.String()) + output := ui.OutputWriter.String() + require.Contains(t, output, "synthetic policy generated from templated policy: builtin/node") + }) + + t.Run("correct input with file", func(t *testing.T) { + ui := cli.NewMockUi() + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-token=root", + "-file=" + testDir + "/templated-policy.hcl", + } + + templatedPolicy := []byte("TemplatedPolicy \"builtin/service\" { Name = \"web\"}") + err := os.WriteFile(testDir+"/templated-policy.hcl", templatedPolicy, 0644) + require.NoError(t, err) + + cmd := New(ui) + code := cmd.Run(args) + assert.Equal(t, code, 0) + assert.Empty(t, ui.ErrorWriter.String()) + output := ui.OutputWriter.String() + require.Contains(t, output, "synthetic policy generated from templated policy: builtin/service") + }) + + t.Run("multiple templated policies input in file", func(t *testing.T) { + ui := cli.NewMockUi() + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-token=root", + "-file=" + testDir + "/templated-policy.hcl", + } + + templatedPolicy := []byte(` + TemplatedPolicy "builtin/service" { Name = "web"} + TemplatedPolicy "builtin/node" { Name = "api"} + `) + err := os.WriteFile(testDir+"/templated-policy.hcl", templatedPolicy, 0644) + require.NoError(t, err) + + cmd := New(ui) + code := cmd.Run(args) + assert.Equal(t, code, 1) + assert.Contains(t, ui.ErrorWriter.String(), "Can only preview a single templated policy at a time.") + }) +} + +func TestTemplatedPolicyPreviewCommand_JSON(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + a := agent.NewTestAgent(t, ` + primary_datacenter = "dc1" + acl { + enabled = true + tokens { + initial_management = "root" + } + }`) + + defer a.Shutdown() + testrpc.WaitForTestAgent(t, a.RPC, "dc1", testrpc.WithToken("root")) + + t.Run("missing templated-policy flags", func(t *testing.T) { + ui := cli.NewMockUi() + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-token=root", + "-format=json", + } + + cmd := New(ui) + code := cmd.Run(args) + assert.Equal(t, code, 1) + assert.Contains(t, ui.ErrorWriter.String(), "Cannot preview a templated policy without specifying -name or -file") + }) + + t.Run("missing required template variables", func(t *testing.T) { + ui := cli.NewMockUi() + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-token=root", + "-name=builtin/node", + "-format=json", + } + + cmd := New(ui) + code := cmd.Run(args) + assert.Equal(t, code, 1) + assert.Contains(t, ui.ErrorWriter.String(), "Failed to generate the templated policy preview") + }) + + t.Run("correct input", func(t *testing.T) { + ui := cli.NewMockUi() + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-token=root", + "-name=builtin/node", + "-var=name:api", + "-format=json", + } + + cmd := New(ui) + code := cmd.Run(args) + assert.Equal(t, code, 0) + assert.Empty(t, ui.ErrorWriter.String()) + output := ui.OutputWriter.String() + require.Contains(t, output, "synthetic policy generated from templated policy: builtin/node") + + // ensure valid json + var jsonOutput json.RawMessage + err := json.Unmarshal([]byte(output), &jsonOutput) + assert.NoError(t, err) + }) +} diff --git a/command/acl/templatedpolicy/read/templated_policy_read.go b/command/acl/templatedpolicy/read/templated_policy_read.go new file mode 100644 index 000000000000..0d3955fb004a --- /dev/null +++ b/command/acl/templatedpolicy/read/templated_policy_read.go @@ -0,0 +1,119 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package templatedpolicyread + +import ( + "flag" + "fmt" + "strings" + + "github.com/mitchellh/cli" + + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/command/acl/templatedpolicy" + "github.com/hashicorp/consul/command/flags" +) + +const ( + PrettyFormat string = "pretty" + JSONFormat string = "json" + synopsis = "Read an ACL Templated Policy" + help = ` +Usage: consul acl templated-policy read [options] TEMPLATED_POLICY + + This command will retrieve and print out the details of a single templated policy. + + Example: + + $ consul acl templated-policy read -name templated-policy-name +` +) + +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.init() + return c +} + +type cmd struct { + UI cli.Ui + flags *flag.FlagSet + http *flags.HTTPFlags + help string + + templateName string + format string + showMeta bool +} + +func (c *cmd) init() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + c.flags.StringVar(&c.templateName, "name", "", "The name of the templated policy to read.") + c.flags.StringVar( + &c.format, + "format", + templatedpolicy.PrettyFormat, + fmt.Sprintf("Output format {%s}", strings.Join(templatedpolicy.GetSupportedFormats(), "|")), + ) + c.flags.BoolVar(&c.showMeta, "meta", false, "Indicates that templated policy metadata such "+ + "as the schema and template code should be shown for each entry.") + c.http = &flags.HTTPFlags{} + flags.Merge(c.flags, c.http.ClientFlags()) + flags.Merge(c.flags, c.http.ServerFlags()) + flags.Merge(c.flags, c.http.MultiTenancyFlags()) + c.help = flags.Usage(help, c.flags) +} + +func (c *cmd) Run(args []string) int { + if err := c.flags.Parse(args); err != nil { + return 1 + } + + if c.templateName == "" { + c.UI.Error("Must specify the -name parameter") + return 1 + } + + client, err := c.http.APIClient() + if err != nil { + c.UI.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err)) + return 1 + } + + var tp *api.ACLTemplatedPolicyResponse + + tp, _, err = client.ACL().TemplatedPolicyReadByName(c.templateName, nil) + if err != nil { + c.UI.Error(fmt.Sprintf("Error reading templated policy %q: %v", c.templateName, err)) + return 1 + } else if tp == nil { + c.UI.Error(fmt.Sprintf("Templated policy not found with name %q", c.templateName)) + return 1 + } + + formatter, err := templatedpolicy.NewFormatter(c.format, c.showMeta) + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + out, err := formatter.FormatTemplatedPolicy(*tp) + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + + if out != "" { + c.UI.Info(out) + } + + return 0 +} + +func (c *cmd) Synopsis() string { + return synopsis +} + +func (c *cmd) Help() string { + return flags.Usage(c.help, nil) +} diff --git a/command/acl/templatedpolicy/read/templated_policy_read_test.go b/command/acl/templatedpolicy/read/templated_policy_read_test.go new file mode 100644 index 000000000000..9059ed99c165 --- /dev/null +++ b/command/acl/templatedpolicy/read/templated_policy_read_test.go @@ -0,0 +1,134 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package templatedpolicyread + +import ( + "encoding/json" + "strings" + "testing" + + "github.com/hashicorp/consul/agent" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/testrpc" + "github.com/mitchellh/cli" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestTemplatedPolicyReadCommand_noTabs(t *testing.T) { + t.Parallel() + + if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') { + t.Fatal("help has tabs") + } +} + +func TestTemplatedPolicyReadCommand(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + a := agent.NewTestAgent(t, ` + primary_datacenter = "dc1" + acl { + enabled = true + tokens { + initial_management = "root" + } + }`) + + defer a.Shutdown() + testrpc.WaitForTestAgent(t, a.RPC, "dc1", testrpc.WithToken("root")) + + t.Run("missing name flag", func(t *testing.T) { + ui := cli.NewMockUi() + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-token=root", + } + + cmd := New(ui) + code := cmd.Run(args) + assert.Equal(t, code, 1) + assert.Contains(t, ui.ErrorWriter.String(), "Must specify the -name parameter") + }) + + t.Run("correct input", func(t *testing.T) { + ui := cli.NewMockUi() + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-token=root", + "-name=" + api.ACLTemplatedPolicyNodeName, + } + + cmd := New(ui) + code := cmd.Run(args) + assert.Equal(t, code, 0) + assert.Empty(t, ui.ErrorWriter.String()) + + output := ui.OutputWriter.String() + require.Contains(t, output, "Name: String - Required - The node name.") + require.Contains(t, output, "consul acl token create -templated-policy builtin/node -var name:node-1") + }) +} + +func TestTemplatedPolicyReadCommand_JSON(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + a := agent.NewTestAgent(t, ` + primary_datacenter = "dc1" + acl { + enabled = true + tokens { + initial_management = "root" + } + }`) + + defer a.Shutdown() + testrpc.WaitForTestAgent(t, a.RPC, "dc1", testrpc.WithToken("root")) + + t.Run("missing name flag", func(t *testing.T) { + ui := cli.NewMockUi() + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-token=root", + "-format=json", + } + + cmd := New(ui) + code := cmd.Run(args) + assert.Equal(t, code, 1) + assert.Contains(t, ui.ErrorWriter.String(), "Must specify the -name parameter") + }) + + t.Run("correct input", func(t *testing.T) { + ui := cli.NewMockUi() + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-token=root", + "-name=" + api.ACLTemplatedPolicyNodeName, + "-format=json", + } + + cmd := New(ui) + code := cmd.Run(args) + assert.Equal(t, code, 0) + assert.Empty(t, ui.ErrorWriter.String()) + + output := ui.OutputWriter.String() + var templatedPolicy api.ACLTemplatedPolicyResponse + err := json.Unmarshal([]byte(output), &templatedPolicy) + + assert.NoError(t, err) + assert.Equal(t, structs.ACLTemplatedPolicyIdentitiesSchema, templatedPolicy.Schema) + assert.Equal(t, api.ACLTemplatedPolicyNodeName, templatedPolicy.TemplateName) + }) +} diff --git a/command/acl/templatedpolicy/templated_policy.go b/command/acl/templatedpolicy/templated_policy.go new file mode 100644 index 000000000000..b6951a075c9b --- /dev/null +++ b/command/acl/templatedpolicy/templated_policy.go @@ -0,0 +1,50 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package templatedpolicy + +import ( + "github.com/hashicorp/consul/command/flags" + "github.com/mitchellh/cli" +) + +func New() *cmd { + return &cmd{} +} + +type cmd struct{} + +func (c *cmd) Run(args []string) int { + return cli.RunResultHelp +} + +func (c *cmd) Synopsis() string { + return synopsis +} + +func (c *cmd) Help() string { + return flags.Usage(help, nil) +} + +const synopsis = "Manage Consul's ACL templated policies" +const help = ` +Usage: consul acl templated-policy [options] [args] + + This command has subcommands for managing Consul ACL templated policies. + Here are some simple examples, and more detailed examples are available + in the subcommands or the documentation. + + List all templated policies: + + $ consul acl templated-policy list + + Preview the policy rendered by the ACL templated policy: + + $ consul acl templated-policy preview -name "builtin/service" -var "name:api" + + Read a templated policy with name: + + $ consul acl templated-policy read -name "builtin/service" + + For more examples, ask for subcommand help or view the documentation. +` diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.json.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.json.golden new file mode 100644 index 000000000000..36682729f1cb --- /dev/null +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.json.golden @@ -0,0 +1,5 @@ +{ + "TemplateName": "builtin/dns", + "Schema": "", + "Template": "\nnode_prefix \"\" {\n\tpolicy = \"read\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}\nquery_prefix \"\" {\n\tpolicy = \"read\"\n}" +} \ No newline at end of file diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.pretty-meta.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.pretty-meta.golden new file mode 100644 index 000000000000..4b63841632ce --- /dev/null +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.pretty-meta.golden @@ -0,0 +1,15 @@ +Name: builtin/dns +Input variables: None +Example usage: + consul acl token create -templated-policy builtin/dns +Raw Template: + +node_prefix "" { + policy = "read" +} +service_prefix "" { + policy = "read" +} +query_prefix "" { + policy = "read" +} diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.pretty.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.pretty.golden new file mode 100644 index 000000000000..012987d03995 --- /dev/null +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.pretty.golden @@ -0,0 +1,4 @@ +Name: builtin/dns +Input variables: None +Example usage: + consul acl token create -templated-policy builtin/dns diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.json.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.json.golden new file mode 100644 index 000000000000..2643a2b9ee02 --- /dev/null +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.json.golden @@ -0,0 +1,5 @@ +{ + "TemplateName": "builtin/node", + "Schema": "\n{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"name\": { \"type\": \"string\", \"$ref\": \"#/definitions/min-length-one\" }\n\t},\n\t\"required\": [\"name\"],\n\t\"definitions\": {\n\t\t\"min-length-one\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"minLength\": 1\n\t\t}\n\t}\n}", + "Template": "\nnode \"{{.Name}}\" {\n\tpolicy = \"write\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}" +} \ No newline at end of file diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.pretty-meta.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.pretty-meta.golden new file mode 100644 index 000000000000..4547a282d74d --- /dev/null +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.pretty-meta.golden @@ -0,0 +1,29 @@ +Name: builtin/node +Input variables: + Name: String - Required - The node name. +Example usage: + consul acl token create -templated-policy builtin/node -var name:node-1 +Schema: + +{ + "type": "object", + "properties": { + "name": { "type": "string", "$ref": "#/definitions/min-length-one" } + }, + "required": ["name"], + "definitions": { + "min-length-one": { + "type": "string", + "minLength": 1 + } + } +} + +Raw Template: + +node "{{.Name}}" { + policy = "write" +} +service_prefix "" { + policy = "read" +} diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.pretty.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.pretty.golden new file mode 100644 index 000000000000..be80ef625c8a --- /dev/null +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.pretty.golden @@ -0,0 +1,5 @@ +Name: builtin/node +Input variables: + Name: String - Required - The node name. +Example usage: + consul acl token create -templated-policy builtin/node -var name:node-1 diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.json.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.json.golden new file mode 100644 index 000000000000..a23b5f8c7ca0 --- /dev/null +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.json.golden @@ -0,0 +1,5 @@ +{ + "TemplateName": "builtin/service", + "Schema": "\n{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"name\": { \"type\": \"string\", \"$ref\": \"#/definitions/min-length-one\" }\n\t},\n\t\"required\": [\"name\"],\n\t\"definitions\": {\n\t\t\"min-length-one\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"minLength\": 1\n\t\t}\n\t}\n}", + "Template": "\nservice \"{{.Name}}\" {\n\tpolicy = \"write\"\n}\nservice \"{{.Name}}-sidecar-proxy\" {\n\tpolicy = \"write\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}\nnode_prefix \"\" {\n\tpolicy = \"read\"\n}" +} \ No newline at end of file diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.pretty-meta.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.pretty-meta.golden new file mode 100644 index 000000000000..d551c2857d15 --- /dev/null +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.pretty-meta.golden @@ -0,0 +1,35 @@ +Name: builtin/service +Input variables: + Name: String - Required - The name of the service. +Example usage: + consul acl token create -templated-policy builtin/service -var name:api +Schema: + +{ + "type": "object", + "properties": { + "name": { "type": "string", "$ref": "#/definitions/min-length-one" } + }, + "required": ["name"], + "definitions": { + "min-length-one": { + "type": "string", + "minLength": 1 + } + } +} + +Raw Template: + +service "{{.Name}}" { + policy = "write" +} +service "{{.Name}}-sidecar-proxy" { + policy = "write" +} +service_prefix "" { + policy = "read" +} +node_prefix "" { + policy = "read" +} diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.pretty.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.pretty.golden new file mode 100644 index 000000000000..ab10d27b2555 --- /dev/null +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.pretty.golden @@ -0,0 +1,5 @@ +Name: builtin/service +Input variables: + Name: String - Required - The name of the service. +Example usage: + consul acl token create -templated-policy builtin/service -var name:api diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicyList/ce/list.json.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicyList/ce/list.json.golden new file mode 100644 index 000000000000..1cb724df8bde --- /dev/null +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicyList/ce/list.json.golden @@ -0,0 +1,17 @@ +{ + "builtin/dns": { + "TemplateName": "builtin/dns", + "Schema": "", + "Template": "\nnode_prefix \"\" {\n\tpolicy = \"read\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}\nquery_prefix \"\" {\n\tpolicy = \"read\"\n}" + }, + "builtin/node": { + "TemplateName": "builtin/node", + "Schema": "\n{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"name\": { \"type\": \"string\", \"$ref\": \"#/definitions/min-length-one\" }\n\t},\n\t\"required\": [\"name\"],\n\t\"definitions\": {\n\t\t\"min-length-one\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"minLength\": 1\n\t\t}\n\t}\n}", + "Template": "\nnode \"{{.Name}}\" {\n\tpolicy = \"write\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}" + }, + "builtin/service": { + "TemplateName": "builtin/service", + "Schema": "\n{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"name\": { \"type\": \"string\", \"$ref\": \"#/definitions/min-length-one\" }\n\t},\n\t\"required\": [\"name\"],\n\t\"definitions\": {\n\t\t\"min-length-one\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"minLength\": 1\n\t\t}\n\t}\n}", + "Template": "\nservice \"{{.Name}}\" {\n\tpolicy = \"write\"\n}\nservice \"{{.Name}}-sidecar-proxy\" {\n\tpolicy = \"write\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}\nnode_prefix \"\" {\n\tpolicy = \"read\"\n}" + } +} \ No newline at end of file diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicyList/ce/list.pretty.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicyList/ce/list.pretty.golden new file mode 100644 index 000000000000..e6080847d424 --- /dev/null +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicyList/ce/list.pretty.golden @@ -0,0 +1,3 @@ +builtin/dns +builtin/node +builtin/service diff --git a/command/acl/token/testdata/FormatTokenExpanded/ce/complex.pretty-meta.golden b/command/acl/token/testdata/FormatTokenExpanded/ce/complex.pretty-meta.golden index 64cfcf0f6402..d8e668cf4a74 100644 --- a/command/acl/token/testdata/FormatTokenExpanded/ce/complex.pretty-meta.golden +++ b/command/acl/token/testdata/FormatTokenExpanded/ce/complex.pretty-meta.golden @@ -26,7 +26,7 @@ Policies: Service Identities: Name: gardener (Datacenters: middleearth-northwest) - Description: synthetic policy for service identity "gardener" + Description: synthetic policy generated from templated policy: builtin/service Rules: service "gardener" { policy = "write" @@ -43,7 +43,7 @@ Service Identities: Node Identities: Name: bagend (Datacenter: middleearth-northwest) - Description: synthetic policy for node identity "bagend" + Description: synthetic policy generated from templated policy: builtin/node Rules: node "bagend" { policy = "write" @@ -96,7 +96,7 @@ Roles: Service Identities: Name: foo (Datacenters: middleearth-southwest) - Description: synthetic policy for service identity "foo" + Description: synthetic policy generated from templated policy: builtin/service Rules: service "foo" { policy = "write" @@ -125,7 +125,7 @@ Roles: Node Identities: Name: bar (Datacenter: middleearth-southwest) - Description: synthetic policy for node identity "bar" + Description: synthetic policy generated from templated policy: builtin/node Rules: node "bar" { policy = "write" @@ -158,7 +158,7 @@ Namespace Role Defaults: Service Identities: Name: web (Datacenters: middleearth-northeast) - Description: synthetic policy for service identity "web" + Description: synthetic policy generated from templated policy: builtin/service Rules: service "web" { policy = "write" @@ -175,7 +175,7 @@ Namespace Role Defaults: Node Identities: Name: db (Datacenter: middleearth-northwest) - Description: synthetic policy for node identity "db" + Description: synthetic policy generated from templated policy: builtin/node Rules: node "db" { policy = "write" diff --git a/command/acl/token/testdata/FormatTokenExpanded/ce/complex.pretty.golden b/command/acl/token/testdata/FormatTokenExpanded/ce/complex.pretty.golden index 18e97e891a5d..f1b31d45193d 100644 --- a/command/acl/token/testdata/FormatTokenExpanded/ce/complex.pretty.golden +++ b/command/acl/token/testdata/FormatTokenExpanded/ce/complex.pretty.golden @@ -23,7 +23,7 @@ Policies: Service Identities: Name: gardener (Datacenters: middleearth-northwest) - Description: synthetic policy for service identity "gardener" + Description: synthetic policy generated from templated policy: builtin/service Rules: service "gardener" { policy = "write" @@ -40,7 +40,7 @@ Service Identities: Node Identities: Name: bagend (Datacenter: middleearth-northwest) - Description: synthetic policy for node identity "bagend" + Description: synthetic policy generated from templated policy: builtin/node Rules: node "bagend" { policy = "write" @@ -93,7 +93,7 @@ Roles: Service Identities: Name: foo (Datacenters: middleearth-southwest) - Description: synthetic policy for service identity "foo" + Description: synthetic policy generated from templated policy: builtin/service Rules: service "foo" { policy = "write" @@ -122,7 +122,7 @@ Roles: Node Identities: Name: bar (Datacenter: middleearth-southwest) - Description: synthetic policy for node identity "bar" + Description: synthetic policy generated from templated policy: builtin/node Rules: node "bar" { policy = "write" @@ -155,7 +155,7 @@ Namespace Role Defaults: Service Identities: Name: web (Datacenters: middleearth-northeast) - Description: synthetic policy for service identity "web" + Description: synthetic policy generated from templated policy: builtin/service Rules: service "web" { policy = "write" @@ -172,7 +172,7 @@ Namespace Role Defaults: Node Identities: Name: db (Datacenter: middleearth-northwest) - Description: synthetic policy for node identity "db" + Description: synthetic policy generated from templated policy: builtin/node Rules: node "db" { policy = "write" diff --git a/command/registry.go b/command/registry.go index fceb7086073b..559189b6f988 100644 --- a/command/registry.go +++ b/command/registry.go @@ -36,6 +36,10 @@ import ( aclrlist "github.com/hashicorp/consul/command/acl/role/list" aclrread "github.com/hashicorp/consul/command/acl/role/read" aclrupdate "github.com/hashicorp/consul/command/acl/role/update" + acltp "github.com/hashicorp/consul/command/acl/templatedpolicy" + acltplist "github.com/hashicorp/consul/command/acl/templatedpolicy/list" + acltppreview "github.com/hashicorp/consul/command/acl/templatedpolicy/preview" + acltpread "github.com/hashicorp/consul/command/acl/templatedpolicy/read" acltoken "github.com/hashicorp/consul/command/acl/token" acltclone "github.com/hashicorp/consul/command/acl/token/clone" acltcreate "github.com/hashicorp/consul/command/acl/token/create" @@ -178,6 +182,10 @@ func RegisteredCommands(ui cli.Ui) map[string]mcli.CommandFactory { entry{"acl binding-rule read", func(ui cli.Ui) (cli.Command, error) { return aclbrread.New(ui), nil }}, entry{"acl binding-rule update", func(ui cli.Ui) (cli.Command, error) { return aclbrupdate.New(ui), nil }}, entry{"acl binding-rule delete", func(ui cli.Ui) (cli.Command, error) { return aclbrdelete.New(ui), nil }}, + entry{"acl templated-policy", func(cli.Ui) (cli.Command, error) { return acltp.New(), nil }}, + entry{"acl templated-policy list", func(ui cli.Ui) (cli.Command, error) { return acltplist.New(ui), nil }}, + entry{"acl templated-policy read", func(ui cli.Ui) (cli.Command, error) { return acltpread.New(ui), nil }}, + entry{"acl templated-policy preview", func(ui cli.Ui) (cli.Command, error) { return acltppreview.New(ui), nil }}, entry{"agent", func(ui cli.Ui) (cli.Command, error) { return agent.New(ui), nil }}, entry{"catalog", func(cli.Ui) (cli.Command, error) { return catalog.New(), nil }}, entry{"catalog datacenters", func(ui cli.Ui) (cli.Command, error) { return catlistdc.New(ui), nil }}, diff --git a/command/resource/apply/apply.go b/command/resource/apply/apply.go index cba9ef30d233..ac0c79d6eaaa 100644 --- a/command/resource/apply/apply.go +++ b/command/resource/apply/apply.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 +// SPDX-License-Identifier: BUSL-1.1 package apply @@ -156,6 +156,7 @@ func (c *cmd) Help() string { } const synopsis = "Writes/updates resource information" + const help = ` Usage: consul resource apply -f= diff --git a/internal/auth/exports.go b/internal/auth/exports.go new file mode 100644 index 000000000000..5dc493546172 --- /dev/null +++ b/internal/auth/exports.go @@ -0,0 +1,41 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package auth + +import ( + "github.com/hashicorp/consul/internal/auth/internal/types" + "github.com/hashicorp/consul/internal/resource" +) + +var ( + // API Group Information + + APIGroup = types.GroupName + VersionV1Alpha1 = types.VersionV1Alpha1 + CurrentVersion = types.CurrentVersion + + // Resource Kind Names. + + WorkloadIdentity = types.WorkloadIdentityKind + TrafficPermissions = types.TrafficPermissionsKind + ComputedTrafficPermissions = types.ComputedTrafficPermissionsKind + + // Resource Types for the v1alpha1 version. + + WorkloadIdentityV1Alpha1Type = types.WorkloadIdentityV1Alpha1Type + TrafficPermissionsV1Alpha1Type = types.TrafficPermissionsV1Alpha1Type + ComputedTrafficPermissionsV1Alpha1Type = types.ComputedTrafficPermissionsV1Alpha1Type + + // Resource Types for the latest version. + + WorkloadIdentityType = types.WorkloadIdentityType + TrafficPermissionsType = types.TrafficPermissionsType + ComputedTrafficPermissionsType = types.ComputedTrafficPermissionsType +) + +// RegisterTypes adds all resource types within the "catalog" API group +// to the given type registry +func RegisterTypes(r resource.Registry) { + types.Register(r) +} diff --git a/internal/auth/internal/types/computed_traffic_permissions.go b/internal/auth/internal/types/computed_traffic_permissions.go new file mode 100644 index 000000000000..753d875f8b1e --- /dev/null +++ b/internal/auth/internal/types/computed_traffic_permissions.go @@ -0,0 +1,33 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package types + +import ( + "github.com/hashicorp/consul/internal/resource" + pbauth "github.com/hashicorp/consul/proto-public/pbauth/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +const ( + ComputedTrafficPermissionsKind = "ComputedTrafficPermission" +) + +var ( + ComputedTrafficPermissionsV1Alpha1Type = &pbresource.Type{ + Group: GroupName, + GroupVersion: VersionV1Alpha1, + Kind: ComputedTrafficPermissionsKind, + } + + ComputedTrafficPermissionsType = ComputedTrafficPermissionsV1Alpha1Type +) + +func RegisterComputedTrafficPermission(r resource.Registry) { + r.Register(resource.Registration{ + Type: ComputedTrafficPermissionsV1Alpha1Type, + Proto: &pbauth.ComputedTrafficPermissions{}, + Scope: resource.ScopeNamespace, + Validate: nil, + }) +} diff --git a/internal/auth/internal/types/errors.go b/internal/auth/internal/types/errors.go new file mode 100644 index 000000000000..a1aab5b419b9 --- /dev/null +++ b/internal/auth/internal/types/errors.go @@ -0,0 +1,12 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package types + +import "errors" + +var ( + errInvalidAction = errors.New("action must be either allow or deny") + errSourcesTenancy = errors.New("permissions sources may not specify partitions, peers, and sameness_groups together") + errInvalidPrefixValues = errors.New("prefix values, regex values, and explicit names must not combined") +) diff --git a/internal/auth/internal/types/traffic_permissions.go b/internal/auth/internal/types/traffic_permissions.go new file mode 100644 index 000000000000..7fa60c5cf2c3 --- /dev/null +++ b/internal/auth/internal/types/traffic_permissions.go @@ -0,0 +1,144 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package types + +import ( + "github.com/hashicorp/go-multierror" + + "github.com/hashicorp/consul/internal/resource" + pbauth "github.com/hashicorp/consul/proto-public/pbauth/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +const ( + TrafficPermissionsKind = "TrafficPermissions" +) + +var ( + TrafficPermissionsV1Alpha1Type = &pbresource.Type{ + Group: GroupName, + GroupVersion: VersionV1Alpha1, + Kind: TrafficPermissionsKind, + } + + TrafficPermissionsType = TrafficPermissionsV1Alpha1Type +) + +func RegisterTrafficPermissions(r resource.Registry) { + r.Register(resource.Registration{ + Type: TrafficPermissionsV1Alpha1Type, + Proto: &pbauth.TrafficPermissions{}, + Scope: resource.ScopeNamespace, + Validate: ValidateTrafficPermissions, + }) +} + +func ValidateTrafficPermissions(res *pbresource.Resource) error { + var tp pbauth.TrafficPermissions + + if err := res.Data.UnmarshalTo(&tp); err != nil { + return resource.NewErrDataParse(&tp, err) + } + + var err error + + if tp.Action == pbauth.Action_ACTION_UNSPECIFIED { + err = multierror.Append(err, resource.ErrInvalidField{ + Name: "data.action", + Wrapped: errInvalidAction, + }) + } + if tp.Destination == nil || (len(tp.Destination.IdentityName) == 0) { + err = multierror.Append(err, resource.ErrInvalidField{ + Name: "data.destination", + Wrapped: resource.ErrEmpty, + }) + } + // Validate permissions + for i, permission := range tp.Permissions { + wrapPermissionErr := func(err error) error { + return resource.ErrInvalidListElement{ + Name: "permissions", + Index: i, + Wrapped: err, + } + } + for s, src := range permission.Sources { + wrapSrcErr := func(err error) error { + return wrapPermissionErr(resource.ErrInvalidListElement{ + Name: "sources", + Index: s, + Wrapped: err, + }) + } + if (len(src.Partition) > 0 && len(src.Peer) > 0) || + (len(src.Partition) > 0 && len(src.SamenessGroup) > 0) || + (len(src.Peer) > 0 && len(src.SamenessGroup) > 0) { + err = multierror.Append(err, wrapSrcErr(resource.ErrInvalidListElement{ + Name: "source", + Wrapped: errSourcesTenancy, + })) + } + if len(src.Exclude) > 0 { + for e, d := range src.Exclude { + wrapExclSrcErr := func(err error) error { + return wrapPermissionErr(resource.ErrInvalidListElement{ + Name: "exclude_sources", + Index: e, + Wrapped: err, + }) + } + if (len(d.Partition) > 0 && len(d.Peer) > 0) || + (len(d.Partition) > 0 && len(d.SamenessGroup) > 0) || + (len(d.Peer) > 0 && len(d.SamenessGroup) > 0) { + err = multierror.Append(err, wrapExclSrcErr(resource.ErrInvalidListElement{ + Name: "exclude_source", + Wrapped: errSourcesTenancy, + })) + } + } + } + } + if len(permission.DestinationRules) > 0 { + for d, dest := range permission.DestinationRules { + wrapDestRuleErr := func(err error) error { + return wrapPermissionErr(resource.ErrInvalidListElement{ + Name: "destination_rules", + Index: d, + Wrapped: err, + }) + } + if (len(dest.PathExact) > 0 && len(dest.PathPrefix) > 0) || + (len(dest.PathRegex) > 0 && len(dest.PathExact) > 0) || + (len(dest.PathRegex) > 0 && len(dest.PathPrefix) > 0) { + err = multierror.Append(err, wrapDestRuleErr(resource.ErrInvalidListElement{ + Name: "destination_rule", + Wrapped: errInvalidPrefixValues, + })) + } + if len(dest.Exclude) > 0 { + for e, excl := range dest.Exclude { + wrapExclPermRuleErr := func(err error) error { + return wrapPermissionErr(resource.ErrInvalidListElement{ + Name: "exclude_permission_rules", + Index: e, + Wrapped: err, + }) + } + if (len(excl.PathExact) > 0 && len(excl.PathPrefix) > 0) || + (len(excl.PathRegex) > 0 && len(excl.PathExact) > 0) || + (len(excl.PathRegex) > 0 && len(excl.PathPrefix) > 0) { + err = multierror.Append(err, wrapExclPermRuleErr(resource.ErrInvalidListElement{ + Name: "exclude_permission_rule", + Wrapped: errInvalidPrefixValues, + })) + } + } + } + } + } + } + + return err +} diff --git a/internal/auth/internal/types/traffic_permissions_test.go b/internal/auth/internal/types/traffic_permissions_test.go new file mode 100644 index 000000000000..09138a78f80a --- /dev/null +++ b/internal/auth/internal/types/traffic_permissions_test.go @@ -0,0 +1,262 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/known/anypb" + + "github.com/hashicorp/consul/internal/resource" + pbauth "github.com/hashicorp/consul/proto-public/pbauth/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +func createTrafficPermissionsResource(t *testing.T, data protoreflect.ProtoMessage) *pbresource.Resource { + res := &pbresource.Resource{ + Id: &pbresource.ID{ + Type: TrafficPermissionsType, + Tenancy: &pbresource.Tenancy{ + Partition: "default", + Namespace: "default", + PeerName: "local", + }, + Name: "test-traffic-permissions", + }, + } + + var err error + res.Data, err = anypb.New(data) + require.NoError(t, err) + return res +} + +func TestTrafficPermissions_OkMinimal(t *testing.T) { + data := &pbauth.TrafficPermissions{ + Destination: &pbauth.Destination{IdentityName: "wi-1"}, + Action: pbauth.Action_ACTION_ALLOW, + } + + res := createTrafficPermissionsResource(t, data) + + err := ValidateTrafficPermissions(res) + require.NoError(t, err) +} + +func TestTrafficPermissions_OkFull(t *testing.T) { + data := &pbauth.TrafficPermissions{ + Destination: &pbauth.Destination{ + IdentityName: "w1", + }, + Action: pbauth.Action_ACTION_ALLOW, + Permissions: []*pbauth.Permission{ + { + Sources: nil, + DestinationRules: []*pbauth.DestinationRule{ + { + PathPrefix: "foo", + Exclude: []*pbauth.ExcludePermissionRule{ + { + PathExact: "baz", + }, + }, + }, + { + PathPrefix: "bar", + }, + }, + }, + { + Sources: []*pbauth.Source{ + { + IdentityName: "wi-3", + Peer: "p1", + }, + }, + }, + }, + } + + res := createTrafficPermissionsResource(t, data) + + err := ValidateTrafficPermissions(res) + require.NoError(t, err) +} + +func TestValidateTrafficPermissions_ParseError(t *testing.T) { + // Any type other than the TrafficPermissions type would work + // to cause the error we are expecting + data := &pbauth.ComputedTrafficPermissions{AllowPermissions: nil} + + res := createTrafficPermissionsResource(t, data) + + err := ValidateTrafficPermissions(res) + require.Error(t, err) + require.ErrorAs(t, err, &resource.ErrDataParse{}) +} + +func TestValidateTrafficPermissions_UnsupportedAction(t *testing.T) { + data := &pbauth.TrafficPermissions{ + Destination: &pbauth.Destination{ + IdentityName: "wi1", + }, + Action: pbauth.Action_ACTION_UNSPECIFIED, + Permissions: nil, + } + + res := createTrafficPermissionsResource(t, data) + + err := ValidateTrafficPermissions(res) + require.Error(t, err) + expected := resource.ErrInvalidField{ + Name: "data.action", + Wrapped: errInvalidAction, + } + var actual resource.ErrInvalidField + require.ErrorAs(t, err, &actual) + require.Equal(t, expected, actual) +} + +func TestValidateTrafficPermissions_DestinationRulePathPrefixRegex(t *testing.T) { + data := &pbauth.TrafficPermissions{ + Destination: &pbauth.Destination{ + IdentityName: "w1", + }, + Action: pbauth.Action_ACTION_ALLOW, + Permissions: []*pbauth.Permission{ + { + Sources: nil, + DestinationRules: []*pbauth.DestinationRule{ + { + PathExact: "wi2", + PathPrefix: "wi", + PathRegex: "wi.*", + }, + }, + }, + }, + } + + res := createTrafficPermissionsResource(t, data) + + err := ValidateTrafficPermissions(res) + require.Error(t, err) + expected := resource.ErrInvalidListElement{ + Name: "destination_rule", + Wrapped: errInvalidPrefixValues, + } + var actual resource.ErrInvalidListElement + require.ErrorAs(t, err, &actual) + require.Equal(t, "permissions", actual.Name) + err = actual.Unwrap() + require.ErrorAs(t, err, &actual) + require.ErrorIs(t, expected, actual.Unwrap()) +} + +func TestValidateTrafficPermissions_NoDestination(t *testing.T) { + data := &pbauth.TrafficPermissions{ + Action: pbauth.Action_ACTION_ALLOW, + Permissions: []*pbauth.Permission{ + { + Sources: nil, + DestinationRules: []*pbauth.DestinationRule{ + { + PathExact: "wi2", + }, + }, + }, + }, + } + + res := createTrafficPermissionsResource(t, data) + + err := ValidateTrafficPermissions(res) + require.Error(t, err) + expected := resource.ErrInvalidField{ + Name: "data.destination", + Wrapped: resource.ErrEmpty, + } + var actual resource.ErrInvalidField + require.ErrorAs(t, err, &actual) + require.Equal(t, "data.destination", actual.Name) + require.Equal(t, expected, actual) +} + +func TestValidateTrafficPermissions_SourceTenancy(t *testing.T) { + data := &pbauth.TrafficPermissions{ + Destination: &pbauth.Destination{ + IdentityName: "w1", + }, + Action: pbauth.Action_ACTION_ALLOW, + Permissions: []*pbauth.Permission{ + { + Sources: []*pbauth.Source{ + { + Partition: "ap1", + Peer: "cl1", + SamenessGroup: "sg1", + }, + }, + DestinationRules: nil, + }, + }, + } + + res := createTrafficPermissionsResource(t, data) + + err := ValidateTrafficPermissions(res) + require.Error(t, err) + expected := resource.ErrInvalidListElement{ + Name: "source", + Wrapped: errSourcesTenancy, + } + var actual resource.ErrInvalidListElement + require.ErrorAs(t, err, &actual) + require.Equal(t, "permissions", actual.Name) + err = actual.Unwrap() + require.ErrorAs(t, err, &actual) + require.ErrorIs(t, expected, actual.Unwrap()) +} + +func TestValidateTrafficPermissions_ExcludeSourceTenancy(t *testing.T) { + data := &pbauth.TrafficPermissions{ + Destination: &pbauth.Destination{ + IdentityName: "w1", + }, + Action: pbauth.Action_ACTION_ALLOW, + Permissions: []*pbauth.Permission{ + { + Sources: []*pbauth.Source{ + { + Namespace: "ns1", + Exclude: []*pbauth.ExcludeSource{ + { + Partition: "ap1", + Peer: "cl1", + SamenessGroup: "sg1", + }, + }, + }, + }, + }, + }, + } + + res := createTrafficPermissionsResource(t, data) + + err := ValidateTrafficPermissions(res) + require.Error(t, err) + expected := resource.ErrInvalidListElement{ + Name: "exclude_source", + Wrapped: errSourcesTenancy, + } + var actual resource.ErrInvalidListElement + require.ErrorAs(t, err, &actual) + require.Equal(t, "permissions", actual.Name) + err = actual.Unwrap() + require.ErrorAs(t, err, &actual) + require.ErrorIs(t, expected, actual.Unwrap()) +} diff --git a/internal/auth/internal/types/types.go b/internal/auth/internal/types/types.go new file mode 100644 index 000000000000..c40812a12573 --- /dev/null +++ b/internal/auth/internal/types/types.go @@ -0,0 +1,20 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package types + +import ( + "github.com/hashicorp/consul/internal/resource" +) + +const ( + GroupName = "auth" + VersionV1Alpha1 = "v1alpha1" + CurrentVersion = VersionV1Alpha1 +) + +func Register(r resource.Registry) { + RegisterWorkloadIdentity(r) + RegisterTrafficPermissions(r) + RegisterComputedTrafficPermission(r) +} diff --git a/internal/auth/internal/types/workload_identity.go b/internal/auth/internal/types/workload_identity.go new file mode 100644 index 000000000000..9b036d5c39e7 --- /dev/null +++ b/internal/auth/internal/types/workload_identity.go @@ -0,0 +1,33 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package types + +import ( + "github.com/hashicorp/consul/internal/resource" + pbauth "github.com/hashicorp/consul/proto-public/pbauth/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +const ( + WorkloadIdentityKind = "WorkloadIdentity" +) + +var ( + WorkloadIdentityV1Alpha1Type = &pbresource.Type{ + Group: GroupName, + GroupVersion: VersionV1Alpha1, + Kind: WorkloadIdentityKind, + } + + WorkloadIdentityType = WorkloadIdentityV1Alpha1Type +) + +func RegisterWorkloadIdentity(r resource.Registry) { + r.Register(resource.Registration{ + Type: WorkloadIdentityV1Alpha1Type, + Proto: &pbauth.WorkloadIdentity{}, + Scope: resource.ScopeNamespace, + Validate: nil, + }) +} diff --git a/internal/catalog/internal/controllers/endpoints/controller.go b/internal/catalog/internal/controllers/endpoints/controller.go index 843130fb4a1a..5a2f8c7d42c2 100644 --- a/internal/catalog/internal/controllers/endpoints/controller.go +++ b/internal/catalog/internal/controllers/endpoints/controller.go @@ -311,8 +311,13 @@ func workloadToEndpoint(svc *pbcatalog.Service, data *workloadData) *pbcatalog.E continue } - if workloadPort.Protocol != svcPort.Protocol { - // workload port mismatch - ignore it + // If workload protocol is not specified, we will default to service's protocol. + // This is because on some platforms (kubernetes), workload protocol is not always + // known, and so we need to inherit from the service instead. + if workloadPort.Protocol == pbcatalog.Protocol_PROTOCOL_UNSPECIFIED { + workloadPort.Protocol = svcPort.Protocol + } else if workloadPort.Protocol != svcPort.Protocol { + // Otherwise, there's workload port mismatch - ignore it. continue } diff --git a/internal/catalog/internal/controllers/endpoints/controller_test.go b/internal/catalog/internal/controllers/endpoints/controller_test.go index bc82874d3b39..4ea84191d1d4 100644 --- a/internal/catalog/internal/controllers/endpoints/controller_test.go +++ b/internal/catalog/internal/controllers/endpoints/controller_test.go @@ -185,6 +185,51 @@ func TestWorkloadToEndpoint_AllAddressesFiltered(t *testing.T) { require.Nil(t, workloadToEndpoint(service, data)) } +func TestWorkloadToEndpoint_MissingWorkloadProtocol(t *testing.T) { + // This test checks that when a workload is missing its protocol, + // we will default to service's protocol. + + service := &pbcatalog.Service{ + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "test-port", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + } + + workload := &pbcatalog.Workload{ + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "127.0.0.1"}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "test-port": {Port: 8080}, + }, + } + + data := &workloadData{ + resource: rtest.Resource(types.WorkloadType, "foo"). + WithData(t, workload). + Build(), + workload: workload, + } + + expected := &pbcatalog.Endpoint{ + TargetRef: data.resource.Id, + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "127.0.0.1", Ports: []string{"test-port"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "test-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + // The health is critical because we are not setting the workload's + // health status. The tests for determineWorkloadHealth will ensure + // that we can properly determine the health status and the overall + // controller tests will prove that the integration works as expected. + HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, + Identity: workload.Identity, + } + + prototest.AssertDeepEqual(t, expected, workloadToEndpoint(service, data)) +} + func TestServiceUnderManagement(t *testing.T) { // This test ensures that we can properly detect when a service // should have endpoints generated for it vs when those endpoints diff --git a/internal/mesh/internal/cache/sidecarproxycache/computed_routes_cache.go b/internal/mesh/internal/cache/sidecarproxycache/computed_routes_cache.go new file mode 100644 index 000000000000..40c9508d2ea4 --- /dev/null +++ b/internal/mesh/internal/cache/sidecarproxycache/computed_routes_cache.go @@ -0,0 +1,47 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package sidecarproxycache + +import ( + "github.com/hashicorp/consul/internal/catalog" + "github.com/hashicorp/consul/internal/mesh/internal/types" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/resource/mappers/bimapper" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +type ComputedRoutesCache struct { + mapper *bimapper.Mapper +} + +func NewComputedRoutesCache() *ComputedRoutesCache { + return &ComputedRoutesCache{ + mapper: bimapper.New(types.ComputedRoutesType, catalog.ServiceType), + } +} + +func (c *ComputedRoutesCache) TrackComputedRoutes(computedRoutes *types.DecodedComputedRoutes) { + var serviceRefs []resource.ReferenceOrID + + for _, pcr := range computedRoutes.Data.PortedConfigs { + for _, details := range pcr.Targets { + serviceRefs = append(serviceRefs, details.BackendRef.Ref) + if details.FailoverConfig != nil { + for _, dest := range details.FailoverConfig.Destinations { + serviceRefs = append(serviceRefs, dest.Ref) + } + } + } + } + + c.mapper.TrackItem(computedRoutes.Resource.Id, serviceRefs) +} + +func (c *ComputedRoutesCache) UntrackComputedRoutes(computedRoutesID *pbresource.ID) { + c.mapper.UntrackItem(computedRoutesID) +} + +func (c *ComputedRoutesCache) ComputedRoutesByService(id resource.ReferenceOrID) []*pbresource.ID { + return c.mapper.ItemIDsForLink(id) +} diff --git a/internal/mesh/internal/cache/sidecarproxycache/destinations_cache.go b/internal/mesh/internal/cache/sidecarproxycache/destinations_cache.go index cd73bdfec85f..d113c568ae07 100644 --- a/internal/mesh/internal/cache/sidecarproxycache/destinations_cache.go +++ b/internal/mesh/internal/cache/sidecarproxycache/destinations_cache.go @@ -24,7 +24,8 @@ type DestinationsCache struct { // store is a map from destination service reference and port as a reference key // to the object representing destination reference. - store map[ReferenceKeyWithPort]intermediate.CombinedDestinationRef + store map[ReferenceKeyWithPort]intermediate.CombinedDestinationRef + storedPorts map[resource.ReferenceKey]map[string]struct{} // sourceProxiesIndex stores a map from a reference key of source proxy IDs // to the keys in the store map. @@ -36,6 +37,7 @@ type storeKeys map[ReferenceKeyWithPort]struct{} func NewDestinationsCache() *DestinationsCache { return &DestinationsCache{ store: make(map[ReferenceKeyWithPort]intermediate.CombinedDestinationRef), + storedPorts: make(map[resource.ReferenceKey]map[string]struct{}), sourceProxiesIndex: make(map[resource.ReferenceKey]storeKeys), } } @@ -87,6 +89,7 @@ func (c *DestinationsCache) addLocked(d intermediate.CombinedDestinationRef) { key := KeyFromRefAndPort(d.ServiceRef, d.Port) c.store[key] = d + c.addPortLocked(d.ServiceRef, d.Port) // Update source proxies index. for proxyRef := range d.SourceProxies { @@ -99,6 +102,18 @@ func (c *DestinationsCache) addLocked(d intermediate.CombinedDestinationRef) { } } +func (c *DestinationsCache) addPortLocked(ref *pbresource.Reference, port string) { + rk := resource.NewReferenceKey(ref) + + m, ok := c.storedPorts[rk] + if !ok { + m = make(map[string]struct{}) + c.storedPorts[rk] = m + } + + m[port] = struct{}{} +} + func (c *DestinationsCache) deleteLocked(ref *pbresource.Reference, port string) { key := KeyFromRefAndPort(ref, port) @@ -117,6 +132,22 @@ func (c *DestinationsCache) deleteLocked(ref *pbresource.Reference, port string) // Finally, delete this destination from the store. delete(c.store, key) + c.deletePortLocked(ref, port) +} + +func (c *DestinationsCache) deletePortLocked(ref *pbresource.Reference, port string) { + rk := resource.NewReferenceKey(ref) + + m, ok := c.storedPorts[rk] + if !ok { + return + } + + delete(m, port) + + if len(m) == 0 { + delete(c.storedPorts, rk) + } } // DeleteSourceProxy deletes the source proxy given by id from the cache. @@ -166,6 +197,35 @@ func (c *DestinationsCache) ReadDestination(ref *pbresource.Reference, port stri return d, found } +func (c *DestinationsCache) ReadDestinationsByServiceAllPorts(ref *pbresource.Reference) []intermediate.CombinedDestinationRef { + // Check that reference is a catalog.Service type. + if !resource.EqualType(catalog.ServiceType, ref.Type) { + panic("ref must of type catalog.Service") + } + + c.lock.RLock() + defer c.lock.RUnlock() + + rk := resource.NewReferenceKey(ref) + + ports, ok := c.storedPorts[rk] + if !ok { + return nil + } + + var destinations []intermediate.CombinedDestinationRef + for port := range ports { + key := KeyFromRefAndPort(ref, port) + + d, found := c.store[key] + if found { + destinations = append(destinations, d) + } + } + + return destinations +} + // DestinationsBySourceProxy returns all destinations that are a referenced by the given source proxy id. func (c *DestinationsCache) DestinationsBySourceProxy(id *pbresource.ID) []intermediate.CombinedDestinationRef { // Check that id is the ProxyStateTemplate type. diff --git a/internal/mesh/internal/cache/sidecarproxycache/destinations_cache_test.go b/internal/mesh/internal/cache/sidecarproxycache/destinations_cache_test.go index 0483af6fd9f2..5e1bbad8a40e 100644 --- a/internal/mesh/internal/cache/sidecarproxycache/destinations_cache_test.go +++ b/internal/mesh/internal/cache/sidecarproxycache/destinations_cache_test.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/resourcetest" "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" ) func TestWrite_Create(t *testing.T) { @@ -190,6 +191,43 @@ func TestDestinationsBySourceProxy(t *testing.T) { require.ElementsMatch(t, expectedDestinations, actualDestinations) } +func TestReadDestinationsByServiceAllPorts(t *testing.T) { + cache := NewDestinationsCache() + + proxyID := resourcetest.Resource(types.ProxyStateTemplateType, "service-workload-abc"). + WithTenancy(resource.DefaultNamespacedTenancy()).ID() + + // test-service@tcp + destination1 := testDestination(proxyID) + cache.WriteDestination(destination1) + + // test-service@tcp2 + destination2 := testDestination(proxyID) + destination2.Port = "tcp2" + cache.WriteDestination(destination2) + + // other-service@tcp + destination3 := testDestination(proxyID) + destination3.ServiceRef = resourcetest.Resource(catalog.ServiceType, "other-service"). + WithTenancy(resource.DefaultNamespacedTenancy()).ReferenceNoSection() + cache.WriteDestination(destination3) + + t.Run("test-service referenced by two ports", func(t *testing.T) { + dests := cache.ReadDestinationsByServiceAllPorts(destination1.ServiceRef) + require.Len(t, dests, 2) + prototest.AssertElementsMatch(t, []intermediate.CombinedDestinationRef{ + destination1, destination2, + }, dests) + }) + t.Run("other-service referenced by one port", func(t *testing.T) { + dests := cache.ReadDestinationsByServiceAllPorts(destination3.ServiceRef) + require.Len(t, dests, 1) + prototest.AssertElementsMatch(t, []intermediate.CombinedDestinationRef{ + destination3, + }, dests) + }) +} + func testDestination(proxyID *pbresource.ID) intermediate.CombinedDestinationRef { return intermediate.CombinedDestinationRef{ ServiceRef: resourcetest.Resource(catalog.ServiceType, "test-service"). diff --git a/internal/mesh/internal/controllers/register.go b/internal/mesh/internal/controllers/register.go index f5c3daf649b3..c98f02b963dd 100644 --- a/internal/mesh/internal/controllers/register.go +++ b/internal/mesh/internal/controllers/register.go @@ -36,11 +36,14 @@ func Register(mgr *controller.Manager, deps Dependencies) { } mgr.Register(xds.Controller(endpointsMapper, deps.ProxyUpdater, deps.TrustBundleFetcher, deps.LeafCertManager, leafMapper, leafCancels, deps.LocalDatacenter)) - destinationsCache := sidecarproxycache.NewDestinationsCache() - proxyCfgCache := sidecarproxycache.NewProxyConfigurationCache() - m := sidecarproxymapper.New(destinationsCache, proxyCfgCache) + var ( + destinationsCache = sidecarproxycache.NewDestinationsCache() + proxyCfgCache = sidecarproxycache.NewProxyConfigurationCache() + computedRoutesCache = sidecarproxycache.NewComputedRoutesCache() + m = sidecarproxymapper.New(destinationsCache, proxyCfgCache, computedRoutesCache) + ) mgr.Register( - sidecarproxy.Controller(destinationsCache, proxyCfgCache, m, deps.TrustDomainFetcher, deps.LocalDatacenter), + sidecarproxy.Controller(destinationsCache, proxyCfgCache, computedRoutesCache, m, deps.TrustDomainFetcher, deps.LocalDatacenter), ) mgr.Register(routes.Controller()) diff --git a/internal/mesh/internal/controllers/routes/controller_test.go b/internal/mesh/internal/controllers/routes/controller_test.go index 4e0923a519fd..bffb187cb103 100644 --- a/internal/mesh/internal/controllers/routes/controller_test.go +++ b/internal/mesh/internal/controllers/routes/controller_test.go @@ -97,7 +97,6 @@ func (suite *controllerSuite) TestController() { UsingDefaultConfig: true, Config: &pbmesh.ComputedPortRoutes_Tcp{ Tcp: &pbmesh.ComputedTCPRoute{ - ParentRef: newParentRef(apiServiceRef, "tcp"), Rules: []*pbmesh.ComputedTCPRouteRule{{ BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ BackendTarget: backendName("api", "tcp"), @@ -105,10 +104,12 @@ func (suite *controllerSuite) TestController() { }}, }, }, + ParentRef: newParentRef(apiServiceRef, "tcp"), + Protocol: pbcatalog.Protocol_PROTOCOL_TCP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("api", "tcp"): { + MeshPort: "mesh", BackendRef: newBackendRef(apiServiceRef, "tcp", ""), - Service: apiServiceData, }, }, }, @@ -164,7 +165,6 @@ func (suite *controllerSuite) TestController() { UsingDefaultConfig: true, Config: &pbmesh.ComputedPortRoutes_Tcp{ Tcp: &pbmesh.ComputedTCPRoute{ - ParentRef: newParentRef(apiServiceRef, "tcp"), Rules: []*pbmesh.ComputedTCPRouteRule{{ BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ BackendTarget: backendName("api", "tcp"), @@ -172,10 +172,12 @@ func (suite *controllerSuite) TestController() { }}, }, }, + ParentRef: newParentRef(apiServiceRef, "tcp"), + Protocol: pbcatalog.Protocol_PROTOCOL_TCP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("api", "tcp"): { + MeshPort: "mesh", BackendRef: newBackendRef(apiServiceRef, "tcp", ""), - Service: apiServiceData, }, }, }, @@ -183,7 +185,6 @@ func (suite *controllerSuite) TestController() { UsingDefaultConfig: true, Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http"), Rules: []*pbmesh.ComputedHTTPRouteRule{{ Matches: []*pbmesh.HTTPRouteMatch{{ Path: &pbmesh.HTTPPathMatch{ @@ -197,10 +198,12 @@ func (suite *controllerSuite) TestController() { }}, }, }, + ParentRef: newParentRef(apiServiceRef, "http"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("api", "http"): { + MeshPort: "mesh", BackendRef: newBackendRef(apiServiceRef, "http", ""), - Service: apiServiceData, }, }, }, @@ -208,7 +211,6 @@ func (suite *controllerSuite) TestController() { UsingDefaultConfig: true, Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http2"), Rules: []*pbmesh.ComputedHTTPRouteRule{{ Matches: []*pbmesh.HTTPRouteMatch{{ Path: &pbmesh.HTTPPathMatch{ @@ -222,10 +224,12 @@ func (suite *controllerSuite) TestController() { }}, }, }, + ParentRef: newParentRef(apiServiceRef, "http2"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("api", "http2"): { + MeshPort: "mesh", BackendRef: newBackendRef(apiServiceRef, "http2", ""), - Service: apiServiceData, }, }, }, @@ -233,7 +237,6 @@ func (suite *controllerSuite) TestController() { UsingDefaultConfig: true, Config: &pbmesh.ComputedPortRoutes_Grpc{ Grpc: &pbmesh.ComputedGRPCRoute{ - ParentRef: newParentRef(apiServiceRef, "grpc"), Rules: []*pbmesh.ComputedGRPCRouteRule{{ Matches: []*pbmesh.GRPCRouteMatch{{}}, BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ @@ -242,10 +245,12 @@ func (suite *controllerSuite) TestController() { }}, }, }, + ParentRef: newParentRef(apiServiceRef, "grpc"), + Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("api", "grpc"): { + MeshPort: "mesh", BackendRef: newBackendRef(apiServiceRef, "grpc", ""), - Service: apiServiceData, }, }, }, @@ -312,7 +317,6 @@ func (suite *controllerSuite) TestController() { "tcp": { Config: &pbmesh.ComputedPortRoutes_Tcp{ Tcp: &pbmesh.ComputedTCPRoute{ - ParentRef: newParentRef(apiServiceRef, "tcp"), Rules: []*pbmesh.ComputedTCPRouteRule{{ BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ BackendTarget: backendName("foo", "tcp"), @@ -320,17 +324,18 @@ func (suite *controllerSuite) TestController() { }}, }, }, + ParentRef: newParentRef(apiServiceRef, "tcp"), + Protocol: pbcatalog.Protocol_PROTOCOL_TCP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "tcp"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "tcp", ""), - Service: fooServiceData, }, }, }, "http": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: defaultHTTPRouteMatches(), @@ -347,17 +352,18 @@ func (suite *controllerSuite) TestController() { }, }, }, + ParentRef: newParentRef(apiServiceRef, "http"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "http"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "http", ""), - Service: fooServiceData, }, }, }, "grpc": { Config: &pbmesh.ComputedPortRoutes_Grpc{ Grpc: &pbmesh.ComputedGRPCRoute{ - ParentRef: newParentRef(apiServiceRef, "grpc"), Rules: []*pbmesh.ComputedGRPCRouteRule{ { Matches: []*pbmesh.GRPCRouteMatch{{}}, @@ -374,17 +380,18 @@ func (suite *controllerSuite) TestController() { }, }, }, + ParentRef: newParentRef(apiServiceRef, "grpc"), + Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "grpc"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "grpc", ""), - Service: fooServiceData, }, }, }, "http2": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http2"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: defaultHTTPRouteMatches(), @@ -401,10 +408,12 @@ func (suite *controllerSuite) TestController() { }, }, }, + ParentRef: newParentRef(apiServiceRef, "http2"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "http2"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "http2", ""), - Service: fooServiceData, }, }, }, @@ -488,7 +497,6 @@ func (suite *controllerSuite) TestController() { "tcp": { Config: &pbmesh.ComputedPortRoutes_Tcp{ Tcp: &pbmesh.ComputedTCPRoute{ - ParentRef: newParentRef(apiServiceRef, "tcp"), Rules: []*pbmesh.ComputedTCPRouteRule{ { BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ @@ -503,17 +511,18 @@ func (suite *controllerSuite) TestController() { }, }, }, + ParentRef: newParentRef(apiServiceRef, "tcp"), + Protocol: pbcatalog.Protocol_PROTOCOL_TCP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "tcp"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "tcp", ""), - Service: fooServiceData, }, }, }, "http": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: []*pbmesh.HTTPRouteMatch{{ @@ -541,17 +550,18 @@ func (suite *controllerSuite) TestController() { }, }, }, + ParentRef: newParentRef(apiServiceRef, "http"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "http"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "http", ""), - Service: fooServiceData, }, }, }, "grpc": { Config: &pbmesh.ComputedPortRoutes_Grpc{ Grpc: &pbmesh.ComputedGRPCRoute{ - ParentRef: newParentRef(apiServiceRef, "grpc"), Rules: []*pbmesh.ComputedGRPCRouteRule{ { Matches: []*pbmesh.GRPCRouteMatch{{}}, @@ -580,17 +590,18 @@ func (suite *controllerSuite) TestController() { }, }, }, + ParentRef: newParentRef(apiServiceRef, "grpc"), + Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "grpc"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "grpc", ""), - Service: fooServiceData, }, }, }, "http2": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http2"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: []*pbmesh.HTTPRouteMatch{{ @@ -618,10 +629,12 @@ func (suite *controllerSuite) TestController() { }, }, }, + ParentRef: newParentRef(apiServiceRef, "http2"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "http2"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "http2", ""), - Service: fooServiceData, }, }, }, @@ -715,7 +728,6 @@ func (suite *controllerSuite) TestController() { "tcp": { Config: &pbmesh.ComputedPortRoutes_Tcp{ Tcp: &pbmesh.ComputedTCPRoute{ - ParentRef: newParentRef(apiServiceRef, "tcp"), Rules: []*pbmesh.ComputedTCPRouteRule{{ BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ BackendTarget: backendName("foo", "tcp"), @@ -723,17 +735,18 @@ func (suite *controllerSuite) TestController() { }}, }, }, + ParentRef: newParentRef(apiServiceRef, "tcp"), + Protocol: pbcatalog.Protocol_PROTOCOL_TCP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "tcp"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "tcp", ""), - Service: fooServiceData, }, }, }, "http": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: defaultHTTPRouteMatches(), @@ -750,17 +763,18 @@ func (suite *controllerSuite) TestController() { }, }, }, + ParentRef: newParentRef(apiServiceRef, "http"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "http"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "http", ""), - Service: fooServiceData, }, }, }, "grpc": { Config: &pbmesh.ComputedPortRoutes_Grpc{ Grpc: &pbmesh.ComputedGRPCRoute{ - ParentRef: newParentRef(apiServiceRef, "grpc"), Rules: []*pbmesh.ComputedGRPCRouteRule{ { Matches: []*pbmesh.GRPCRouteMatch{{}}, @@ -777,17 +791,18 @@ func (suite *controllerSuite) TestController() { }, }, }, + ParentRef: newParentRef(apiServiceRef, "grpc"), + Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "grpc"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "grpc", ""), - Service: fooServiceData, }, }, }, "http2": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http2"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: defaultHTTPRouteMatches(), @@ -804,10 +819,12 @@ func (suite *controllerSuite) TestController() { }, }, }, + ParentRef: newParentRef(apiServiceRef, "http2"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "http2"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "http2", ""), - Service: fooServiceData, }, }, }, @@ -866,7 +883,6 @@ func (suite *controllerSuite) TestController() { "tcp": { Config: &pbmesh.ComputedPortRoutes_Tcp{ Tcp: &pbmesh.ComputedTCPRoute{ - ParentRef: newParentRef(apiServiceRef, "tcp"), Rules: []*pbmesh.ComputedTCPRouteRule{{ BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ BackendTarget: backendName("foo", "tcp"), @@ -874,17 +890,18 @@ func (suite *controllerSuite) TestController() { }}, }, }, + ParentRef: newParentRef(apiServiceRef, "tcp"), + Protocol: pbcatalog.Protocol_PROTOCOL_TCP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "tcp"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "tcp", ""), - Service: fooServiceData, }, }, }, "http": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: defaultHTTPRouteMatches(), @@ -901,17 +918,18 @@ func (suite *controllerSuite) TestController() { }, }, }, + ParentRef: newParentRef(apiServiceRef, "http"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "http"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "http", ""), - Service: fooServiceData, }, }, }, "grpc": { Config: &pbmesh.ComputedPortRoutes_Grpc{ Grpc: &pbmesh.ComputedGRPCRoute{ - ParentRef: newParentRef(apiServiceRef, "grpc"), Rules: []*pbmesh.ComputedGRPCRouteRule{ { Matches: []*pbmesh.GRPCRouteMatch{{}}, @@ -928,17 +946,18 @@ func (suite *controllerSuite) TestController() { }, }, }, + ParentRef: newParentRef(apiServiceRef, "grpc"), + Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "grpc"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "grpc", ""), - Service: fooServiceData, }, }, }, "http2": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http2"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: defaultHTTPRouteMatches(), @@ -955,10 +974,12 @@ func (suite *controllerSuite) TestController() { }, }, }, + ParentRef: newParentRef(apiServiceRef, "http2"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "http2"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "http2", ""), - Service: fooServiceData, }, }, }, diff --git a/internal/mesh/internal/controllers/routes/generate.go b/internal/mesh/internal/controllers/routes/generate.go index 72fca36ab55b..42ecc56ff701 100644 --- a/internal/mesh/internal/controllers/routes/generate.go +++ b/internal/mesh/internal/controllers/routes/generate.go @@ -217,42 +217,53 @@ func compile( // Inject catch-all rules to ensure stray requests will explicitly be blackholed. if !top.Default { - if !types.IsTCPRouteType(top.RouteType) { + if types.IsTCPRouteType(top.RouteType) { + if len(top.TCPRules) == 0 { + // User requests traffic blackhole. + appendDefaultRouteNode(top, types.NullRouteBackend) + } + } else { // There are no match criteria on a TCPRoute, so never a need // to add a catch-all. appendDefaultRouteNode(top, types.NullRouteBackend) } } - mc := &pbmesh.ComputedPortRoutes{ - UsingDefaultConfig: top.Default, - Targets: top.NewTargets, - } parentRef := &pbmesh.ParentReference{ Ref: parentServiceRef, Port: port, } + mc := &pbmesh.ComputedPortRoutes{ + UsingDefaultConfig: top.Default, + ParentRef: parentRef, + Protocol: allowedPortProtocols[port], + Targets: top.NewTargets, + } + switch { case resource.EqualType(top.RouteType, types.HTTPRouteType): + if mc.Protocol == pbcatalog.Protocol_PROTOCOL_TCP { + // The rest are HTTP-like + mc.Protocol = pbcatalog.Protocol_PROTOCOL_HTTP + } mc.Config = &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: parentRef, - Rules: top.HTTPRules, + Rules: top.HTTPRules, }, } case resource.EqualType(top.RouteType, types.GRPCRouteType): + mc.Protocol = pbcatalog.Protocol_PROTOCOL_GRPC mc.Config = &pbmesh.ComputedPortRoutes_Grpc{ Grpc: &pbmesh.ComputedGRPCRoute{ - ParentRef: parentRef, - Rules: top.GRPCRules, + Rules: top.GRPCRules, }, } case resource.EqualType(top.RouteType, types.TCPRouteType): + mc.Protocol = pbcatalog.Protocol_PROTOCOL_TCP mc.Config = &pbmesh.ComputedPortRoutes_Tcp{ Tcp: &pbmesh.ComputedTCPRoute{ - ParentRef: parentRef, - Rules: top.TCPRules, + Rules: top.TCPRules, }, } default: @@ -266,21 +277,37 @@ func compile( svc := related.GetService(svcRef) failoverPolicy := related.GetFailoverPolicyForService(svcRef) - destConfig := related.GetDestinationPolicyForService(svcRef) + destPolicy := related.GetDestinationPolicyForService(svcRef) if svc == nil { panic("impossible at this point; should already have been handled before getting here") } - details.Service = svc.Data + + // Find the destination proxy's port. + // + // Endpoints refs will need to route to mesh port instead of the + // destination port as that is the port of the destination's proxy. + // + // Note: we will always find a port here because we only add targets that have + // mesh ports above in shouldRouteTrafficToBackend(). + for _, port := range svc.Data.Ports { + if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { + details.MeshPort = port.TargetPort + } + } if failoverPolicy != nil { - details.FailoverPolicy = catalog.SimplifyFailoverPolicy( - svc.Data, - failoverPolicy.Data, - ) + simpleFailoverPolicy := catalog.SimplifyFailoverPolicy(svc.Data, failoverPolicy.Data) + portFailoverConfig, ok := simpleFailoverPolicy.PortConfigs[details.BackendRef.Port] + if ok { + details.FailoverConfig = portFailoverConfig + } } - if destConfig != nil { - details.DestinationPolicy = destConfig.Data + if destPolicy != nil { + portDestConfig, ok := destPolicy.Data.PortConfigs[details.BackendRef.Port] + if ok { + details.DestinationConfig = portDestConfig + } } } diff --git a/internal/mesh/internal/controllers/routes/generate_test.go b/internal/mesh/internal/controllers/routes/generate_test.go index 02bb7ea695e5..e46bc57f0119 100644 --- a/internal/mesh/internal/controllers/routes/generate_test.go +++ b/internal/mesh/internal/controllers/routes/generate_test.go @@ -183,7 +183,6 @@ func TestGenerateComputedRoutes(t *testing.T) { "tcp": { Config: &pbmesh.ComputedPortRoutes_Tcp{ Tcp: &pbmesh.ComputedTCPRoute{ - ParentRef: newParentRef(apiServiceRef, "tcp"), Rules: []*pbmesh.ComputedTCPRouteRule{{ BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ BackendTarget: backendName("api", "tcp"), @@ -192,10 +191,12 @@ func TestGenerateComputedRoutes(t *testing.T) { }, }, UsingDefaultConfig: true, + ParentRef: newParentRef(apiServiceRef, "tcp"), + Protocol: pbcatalog.Protocol_PROTOCOL_TCP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("api", "tcp"): { + MeshPort: "mesh", BackendRef: newBackendRef(apiServiceRef, "tcp", ""), - Service: apiServiceData, }, }, }, @@ -232,7 +233,6 @@ func TestGenerateComputedRoutes(t *testing.T) { protoName: { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, protoName), Rules: []*pbmesh.ComputedHTTPRouteRule{{ Matches: []*pbmesh.HTTPRouteMatch{{ Path: &pbmesh.HTTPPathMatch{ @@ -247,10 +247,12 @@ func TestGenerateComputedRoutes(t *testing.T) { }, }, UsingDefaultConfig: true, + ParentRef: newParentRef(apiServiceRef, protoName), + Protocol: protocol, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("api", protoName): { + MeshPort: "mesh", BackendRef: newBackendRef(apiServiceRef, protoName, ""), - Service: apiServiceData, }, }, }, @@ -284,7 +286,6 @@ func TestGenerateComputedRoutes(t *testing.T) { "grpc": { Config: &pbmesh.ComputedPortRoutes_Grpc{ Grpc: &pbmesh.ComputedGRPCRoute{ - ParentRef: newParentRef(apiServiceRef, "grpc"), Rules: []*pbmesh.ComputedGRPCRouteRule{{ Matches: []*pbmesh.GRPCRouteMatch{{}}, BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ @@ -294,10 +295,12 @@ func TestGenerateComputedRoutes(t *testing.T) { }, }, UsingDefaultConfig: true, + ParentRef: newParentRef(apiServiceRef, "grpc"), + Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("api", "grpc"): { + MeshPort: "mesh", BackendRef: newBackendRef(apiServiceRef, "grpc", ""), - Service: apiServiceData, }, }, }, @@ -386,7 +389,6 @@ func TestGenerateComputedRoutes(t *testing.T) { "tcp": { Config: &pbmesh.ComputedPortRoutes_Tcp{ Tcp: &pbmesh.ComputedTCPRoute{ - ParentRef: newParentRef(apiServiceRef, "tcp"), Rules: []*pbmesh.ComputedTCPRouteRule{{ BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ BackendTarget: backendName("foo", "tcp"), @@ -394,17 +396,18 @@ func TestGenerateComputedRoutes(t *testing.T) { }}, }, }, + ParentRef: newParentRef(apiServiceRef, "tcp"), + Protocol: pbcatalog.Protocol_PROTOCOL_TCP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "tcp"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "tcp", ""), - Service: fooServiceData, }, }, }, "http": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: defaultHTTPRouteMatches(), @@ -421,17 +424,18 @@ func TestGenerateComputedRoutes(t *testing.T) { }, }, }, + ParentRef: newParentRef(apiServiceRef, "http"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "http"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "http", ""), - Service: fooServiceData, }, }, }, "http2": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http2"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: defaultHTTPRouteMatches(), @@ -448,17 +452,18 @@ func TestGenerateComputedRoutes(t *testing.T) { }, }, }, + ParentRef: newParentRef(apiServiceRef, "http2"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "http2"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "http2", ""), - Service: fooServiceData, }, }, }, "grpc": { Config: &pbmesh.ComputedPortRoutes_Grpc{ Grpc: &pbmesh.ComputedGRPCRoute{ - ParentRef: newParentRef(apiServiceRef, "grpc"), Rules: []*pbmesh.ComputedGRPCRouteRule{ { Matches: []*pbmesh.GRPCRouteMatch{{}}, @@ -475,10 +480,12 @@ func TestGenerateComputedRoutes(t *testing.T) { }, }, }, + ParentRef: newParentRef(apiServiceRef, "grpc"), + Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "grpc"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "grpc", ""), - Service: fooServiceData, }, }, }, @@ -534,11 +541,10 @@ func TestGenerateComputedRoutes(t *testing.T) { newHTTPRoute("api-http-route1", httpRoute1), ) - chunk := func(portName string) *pbmesh.ComputedPortRoutes { + chunk := func(portName string, protocol pbcatalog.Protocol) *pbmesh.ComputedPortRoutes { return &pbmesh.ComputedPortRoutes{ Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, portName), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: defaultHTTPRouteMatches(), @@ -555,10 +561,12 @@ func TestGenerateComputedRoutes(t *testing.T) { }, }, }, + ParentRef: newParentRef(apiServiceRef, portName), + Protocol: protocol, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", portName): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, portName, ""), - Service: fooServiceData, }, }, } @@ -569,10 +577,11 @@ func TestGenerateComputedRoutes(t *testing.T) { OwnerID: apiServiceID, Data: &pbmesh.ComputedRoutes{ PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "tcp": chunk("tcp"), - "http": chunk("http"), - "http2": chunk("http2"), - "grpc": chunk("grpc"), + // note: tcp has been upgraded to http in the presence of an HTTPRoute + "tcp": chunk("tcp", pbcatalog.Protocol_PROTOCOL_HTTP), + "http": chunk("http", pbcatalog.Protocol_PROTOCOL_HTTP), + "http2": chunk("http2", pbcatalog.Protocol_PROTOCOL_HTTP2), + "grpc": chunk("grpc", pbcatalog.Protocol_PROTOCOL_GRPC), }, }, }} @@ -638,7 +647,6 @@ func TestGenerateComputedRoutes(t *testing.T) { "http": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http"), Rules: []*pbmesh.ComputedHTTPRouteRule{{ Matches: []*pbmesh.HTTPRouteMatch{{ Path: &pbmesh.HTTPPathMatch{ @@ -653,10 +661,12 @@ func TestGenerateComputedRoutes(t *testing.T) { }, }, UsingDefaultConfig: true, + ParentRef: newParentRef(apiServiceRef, "http"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("api", "http"): { + MeshPort: "mesh", BackendRef: newBackendRef(apiServiceRef, "http", ""), - Service: apiServiceData, }, }, }, @@ -715,7 +725,6 @@ func TestGenerateComputedRoutes(t *testing.T) { "http": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http"), Rules: []*pbmesh.ComputedHTTPRouteRule{{ Matches: []*pbmesh.HTTPRouteMatch{{ Path: &pbmesh.HTTPPathMatch{ @@ -730,10 +739,12 @@ func TestGenerateComputedRoutes(t *testing.T) { }, }, UsingDefaultConfig: true, + ParentRef: newParentRef(apiServiceRef, "http"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("api", "http"): { + MeshPort: "mesh", BackendRef: newBackendRef(apiServiceRef, "http", ""), - Service: apiServiceData, }, }, }, @@ -812,7 +823,6 @@ func TestGenerateComputedRoutes(t *testing.T) { "http": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: defaultHTTPRouteMatches(), @@ -829,10 +839,12 @@ func TestGenerateComputedRoutes(t *testing.T) { }, }, }, + ParentRef: newParentRef(apiServiceRef, "http"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "http"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "http", ""), - Service: fooServiceData, }, }, }, @@ -939,7 +951,6 @@ func TestGenerateComputedRoutes(t *testing.T) { "http": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: []*pbmesh.HTTPRouteMatch{{ @@ -972,14 +983,16 @@ func TestGenerateComputedRoutes(t *testing.T) { }, }, }, + ParentRef: newParentRef(apiServiceRef, "http"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "http"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "http", ""), - Service: fooServiceData, }, backendName("bar", "http"): { + MeshPort: "mesh", BackendRef: newBackendRef(barServiceRef, "http", ""), - Service: barServiceData, }, }, }, @@ -1040,7 +1053,6 @@ func TestGenerateComputedRoutes(t *testing.T) { "http": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: defaultHTTPRouteMatches(), @@ -1057,10 +1069,12 @@ func TestGenerateComputedRoutes(t *testing.T) { }, }, }, + ParentRef: newParentRef(apiServiceRef, "http"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "http"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "http", ""), - Service: fooServiceData, }, }, }, @@ -1106,9 +1120,10 @@ func TestGenerateComputedRoutes(t *testing.T) { Data: &pbmesh.ComputedRoutes{ PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ "http": { + ParentRef: newParentRef(apiServiceRef, "http"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: defaultHTTPRouteMatches(), @@ -1166,9 +1181,10 @@ func TestGenerateComputedRoutes(t *testing.T) { Data: &pbmesh.ComputedRoutes{ PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ "grpc": { + ParentRef: newParentRef(apiServiceRef, "grpc"), + Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, Config: &pbmesh.ComputedPortRoutes_Grpc{ Grpc: &pbmesh.ComputedGRPCRoute{ - ParentRef: newParentRef(apiServiceRef, "grpc"), Rules: []*pbmesh.ComputedGRPCRouteRule{ { Matches: defaultGRPCRouteMatches(), @@ -1226,9 +1242,10 @@ func TestGenerateComputedRoutes(t *testing.T) { Data: &pbmesh.ComputedRoutes{ PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ "tcp": { + ParentRef: newParentRef(apiServiceRef, "tcp"), + Protocol: pbcatalog.Protocol_PROTOCOL_TCP, Config: &pbmesh.ComputedPortRoutes_Tcp{ Tcp: &pbmesh.ComputedTCPRoute{ - ParentRef: newParentRef(apiServiceRef, "tcp"), Rules: []*pbmesh.ComputedTCPRouteRule{ { BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ @@ -1291,9 +1308,10 @@ func TestGenerateComputedRoutes(t *testing.T) { Data: &pbmesh.ComputedRoutes{ PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ "http": { + ParentRef: newParentRef(apiServiceRef, "http"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: defaultHTTPRouteMatches(), @@ -1362,6 +1380,9 @@ func TestGenerateComputedRoutes(t *testing.T) { }, }, } + portDestConfig := &pbmesh.DestinationConfig{ + ConnectTimeout: durationpb.New(55 * time.Second), + } related := loader.NewRelatedResources(). AddComputedRoutesIDs(apiComputedRoutesID). @@ -1380,7 +1401,6 @@ func TestGenerateComputedRoutes(t *testing.T) { "http": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: defaultHTTPRouteMatches(), @@ -1397,11 +1417,13 @@ func TestGenerateComputedRoutes(t *testing.T) { }, }, }, + ParentRef: newParentRef(apiServiceRef, "http"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "http"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "http", ""), - Service: fooServiceData, - DestinationPolicy: destPolicy, + DestinationConfig: portDestConfig, }, }, }, @@ -1466,15 +1488,11 @@ func TestGenerateComputedRoutes(t *testing.T) { }}, }, } - simplifiedFailoverPolicy := &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: barServiceRef, - Port: "http", - }}, - }, - }, + portFailoverConfig := &pbcatalog.FailoverConfig{ + Destinations: []*pbcatalog.FailoverDestination{{ + Ref: barServiceRef, + Port: "http", + }}, } related := loader.NewRelatedResources(). @@ -1495,7 +1513,6 @@ func TestGenerateComputedRoutes(t *testing.T) { "http": { Config: &pbmesh.ComputedPortRoutes_Http{ Http: &pbmesh.ComputedHTTPRoute{ - ParentRef: newParentRef(apiServiceRef, "http"), Rules: []*pbmesh.ComputedHTTPRouteRule{ { Matches: defaultHTTPRouteMatches(), @@ -1512,11 +1529,13 @@ func TestGenerateComputedRoutes(t *testing.T) { }, }, }, + ParentRef: newParentRef(apiServiceRef, "http"), + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Targets: map[string]*pbmesh.BackendTargetDetails{ backendName("foo", "http"): { + MeshPort: "mesh", BackendRef: newBackendRef(fooServiceRef, "http", ""), - Service: fooServiceData, - FailoverPolicy: simplifiedFailoverPolicy, + FailoverConfig: portFailoverConfig, }, }, }, diff --git a/internal/mesh/internal/controllers/routes/routestest/routestest.go b/internal/mesh/internal/controllers/routes/routestest/routestest.go new file mode 100644 index 000000000000..52ddd1dcaa40 --- /dev/null +++ b/internal/mesh/internal/controllers/routes/routestest/routestest.go @@ -0,0 +1,111 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package routestest + +import ( + "testing" + + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + + "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes" + "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/loader" + "github.com/hashicorp/consul/internal/mesh/internal/types" + "github.com/hashicorp/consul/internal/resource" + rtest "github.com/hashicorp/consul/internal/resource/resourcetest" + pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/sdk/testutil" +) + +func ReconcileComputedRoutes( + t *testing.T, + client pbresource.ResourceServiceClient, + id *pbresource.ID, + decResList ...any, +) *types.DecodedComputedRoutes { + t.Helper() + if client == nil { + panic("client is required") + } + return makeComputedRoutes(t, client, id, decResList...) +} + +func BuildComputedRoutes( + t *testing.T, + id *pbresource.ID, + decResList ...any, +) *types.DecodedComputedRoutes { + t.Helper() + return makeComputedRoutes(t, nil, id, decResList...) +} + +func MutateTarget( + t *testing.T, + portConfig *pbmesh.ComputedPortRoutes, + ref resource.ReferenceOrID, + port string, + mutFn func(details *pbmesh.BackendTargetDetails), +) *pbmesh.ComputedPortRoutes { + t.Helper() + + backendRef := &pbmesh.BackendReference{ + Ref: resource.ReferenceFromReferenceOrID(ref), + Port: port, + Datacenter: "", + } + + key := types.BackendRefToComputedRoutesTarget(backendRef) + + portConfig = proto.Clone(portConfig).(*pbmesh.ComputedPortRoutes) + + details, ok := portConfig.Targets[key] + require.True(t, ok, "key %q not found in targets map", key) + + mutFn(details) + return portConfig +} + +func makeComputedRoutes( + t *testing.T, + client pbresource.ResourceServiceClient, + id *pbresource.ID, + decResList ...any, +) *types.DecodedComputedRoutes { + t.Helper() + + related := loader.NewRelatedResources(). + AddComputedRoutesID(id). + AddResources(decResList...) + + pending := make(routes.PendingStatuses) + got := routes.GenerateComputedRoutes(related, pending) + require.Empty(t, pending, "programmer error if there are warnings") + require.Len(t, got, 1, "should only compute one output") + + item := got[0] + + if item.Data == nil { + if client != nil { + ctx := testutil.TestContext(t) + _, err := client.Delete(ctx, &pbresource.DeleteRequest{Id: got[0].ID}) + require.NoError(t, err) + } + return nil + } + + b := rtest.ResourceID(id). + // WithOwner(item.OwnerID). + WithData(t, item.Data) + + var res *pbresource.Resource + if client != nil { + res = b.Write(t, client) + } else { + res = b.Build() + } + require.NoError(t, types.ValidateComputedRoutes(res)) + + return rtest.MustDecode[*pbmesh.ComputedRoutes](t, res) +} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/builder.go b/internal/mesh/internal/controllers/sidecarproxy/builder/builder.go index d6e7ac0d4f07..a76af3b653b3 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/builder.go +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/builder.go @@ -16,17 +16,15 @@ type Builder struct { proxyCfg *pbmesh.ProxyConfiguration trustDomain string localDatacenter string - - outboundListenerBuilder *ListenerBuilder } -func New(id *pbresource.ID, +func New( + id *pbresource.ID, identity *pbresource.Reference, trustDomain string, dc string, proxyCfg *pbmesh.ProxyConfiguration, ) *Builder { - return &Builder{ id: id, trustDomain: trustDomain, @@ -37,6 +35,7 @@ func New(id *pbresource.ID, Identity: identity, Clusters: make(map[string]*pbproxystate.Cluster), Endpoints: make(map[string]*pbproxystate.Endpoints), + Routes: make(map[string]*pbproxystate.Route), }, RequiredEndpoints: make(map[string]*pbproxystate.EndpointRef), RequiredLeafCertificates: make(map[string]*pbproxystate.LeafCertificateRef), @@ -61,8 +60,22 @@ func (b *Builder) NewListenerBuilder(l *pbproxystate.Listener) *ListenerBuilder } } -func (l *ListenerBuilder) buildListener() *Builder { +func (l *ListenerBuilder) buildListener() { l.builder.proxyStateTemplate.ProxyState.Listeners = append(l.builder.proxyStateTemplate.ProxyState.Listeners, l.listener) +} + +type RouterBuilder struct { + router *pbproxystate.Router + builder *ListenerBuilder +} + +func (b *ListenerBuilder) NewRouterBuilder(r *pbproxystate.Router) *RouterBuilder { + return &RouterBuilder{ + router: r, + builder: b, + } +} - return l.builder +func (r *RouterBuilder) buildRouter() { + r.builder.listener.Routers = append(r.builder.listener.Routers, r.router) } diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/destination_builder.go b/internal/mesh/internal/controllers/sidecarproxy/builder/destination_builder.go index 225859226da6..f0b02031d9a0 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/destination_builder.go +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/destination_builder.go @@ -5,13 +5,16 @@ package builder import ( "fmt" + "time" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/wrapperspb" "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/envoyextensions/xdscommon" + "github.com/hashicorp/consul/internal/mesh/internal/types" "github.com/hashicorp/consul/internal/mesh/internal/types/intermediate" - "github.com/hashicorp/consul/internal/resource" pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" @@ -21,91 +24,373 @@ import ( // BuildDestinations creates listeners, routers, clusters, and endpointRefs for all destinations // and adds them to the proxyState. func (b *Builder) BuildDestinations(destinations []*intermediate.Destination) *Builder { + var lb *ListenerBuilder if b.proxyCfg.GetDynamicConfig() != nil && b.proxyCfg.DynamicConfig.Mode == pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT { - b.addTransparentProxyOutboundListener(b.proxyCfg.DynamicConfig.TransparentProxy.OutboundListenerPort) + lb = b.addTransparentProxyOutboundListener(b.proxyCfg.DynamicConfig.TransparentProxy.OutboundListenerPort) } for _, destination := range destinations { + b.buildDestination(lb, destination) + } + + return b +} + +func (b *Builder) buildDestination( + tproxyOutboundListenerBuilder *ListenerBuilder, + destination *intermediate.Destination, +) *Builder { + var ( + effectiveProtocol = destination.ComputedPortRoutes.Protocol + targets = destination.ComputedPortRoutes.Targets + ) + + cpr := destination.ComputedPortRoutes + + var lb *ListenerBuilder + if destination.Explicit != nil { + lb = b.addExplicitOutboundListener(destination.Explicit) + } else { + lb = tproxyOutboundListenerBuilder + } + + // router matches based on destination ports should only occur on + // implicit destinations for explicit + var virtualPortNumber uint32 + if destination.Explicit == nil { + for _, port := range destination.Service.Data.Ports { + if port.TargetPort == cpr.ParentRef.Port { + virtualPortNumber = port.VirtualPort + } + } + } + + defaultDC := func(dc string) string { if destination.Explicit != nil { - b.buildExplicitDestination(destination) - } else { - b.buildImplicitDestination(destination) + dc = orDefault(dc, destination.Explicit.Datacenter) + } + dc = orDefault(dc, b.localDatacenter) + if dc != b.localDatacenter { + panic("cross datacenter service discovery clusters are not supported in v2") + } + return dc + } + + statPrefix := DestinationStatPrefix( + cpr.ParentRef.Ref, + cpr.ParentRef.Port, + defaultDC(""), + ) + + var ( + useRDS bool + needsNullRouteCluster bool + ) + switch config := cpr.Config.(type) { + case *pbmesh.ComputedPortRoutes_Http: + // NOTE: this could be HTTP/HTTP2/GRPC + useRDS = true + + route := config.Http + + listenerName := lb.listener.Name + + // this corresponds to roughly "makeUpstreamRouteForDiscoveryChain" + + var proxyRouteRules []*pbproxystate.RouteRule + for _, routeRule := range route.Rules { + for _, backendRef := range routeRule.BackendRefs { + if backendRef.BackendTarget == types.NullRouteBackend { + needsNullRouteCluster = true + } + } + destConfig := b.makeDestinationConfiguration(routeRule.Timeouts, routeRule.Retries) + + dest := b.makeHTTPRouteDestination( + routeRule.BackendRefs, + destConfig, + targets, + defaultDC, + ) + + // TODO(rb/v2): Filters []*HTTPRouteFilter + // TODO(rb/v2): BackendRefs []*ComputedHTTPBackendRef + + // Explode out by matches + for _, match := range routeRule.Matches { + routeMatch := makeHTTPRouteMatch(match) + + proxyRouteRules = append(proxyRouteRules, &pbproxystate.RouteRule{ + Match: routeMatch, + Destination: proto.Clone(dest).(*pbproxystate.RouteDestination), + // TODO: mutations + }) + } + } + + b.addRoute(listenerName, &pbproxystate.Route{ + VirtualHosts: []*pbproxystate.VirtualHost{{ + Name: listenerName, + RouteRules: proxyRouteRules, + }}, + }) + + case *pbmesh.ComputedPortRoutes_Grpc: + useRDS = true + route := config.Grpc + + listenerName := lb.listener.Name + + var proxyRouteRules []*pbproxystate.RouteRule + for _, routeRule := range route.Rules { + for _, backendRef := range routeRule.BackendRefs { + if backendRef.BackendTarget == types.NullRouteBackend { + needsNullRouteCluster = true + } + } + destConfig := b.makeDestinationConfiguration(routeRule.Timeouts, routeRule.Retries) + + // nolint:staticcheck + dest := b.makeGRPCRouteDestination( + routeRule.BackendRefs, + destConfig, + targets, + defaultDC, + ) + + // TODO(rb/v2): Filters []*HTTPRouteFilter + + // Explode out by matches + for _, match := range routeRule.Matches { + routeMatch := makeGRPCRouteMatch(match) + + proxyRouteRules = append(proxyRouteRules, &pbproxystate.RouteRule{ + Match: routeMatch, + Destination: proto.Clone(dest).(*pbproxystate.RouteDestination), + // TODO: mutations + }) + } + } + + b.addRoute(listenerName, &pbproxystate.Route{ + VirtualHosts: []*pbproxystate.VirtualHost{{ + Name: listenerName, + RouteRules: proxyRouteRules, + }}, + }) + + case *pbmesh.ComputedPortRoutes_Tcp: + route := config.Tcp + useRDS = false + + if len(route.Rules) != 1 { + panic("not possible due to validation and computation") + } + + // When not using RDS we must generate a cluster name to attach to + // the filter chain. With RDS, cluster names get attached to the + // dynamic routes instead. + + routeRule := route.Rules[0] + + for _, backendRef := range routeRule.BackendRefs { + if backendRef.BackendTarget == types.NullRouteBackend { + needsNullRouteCluster = true + } + } + + switch len(routeRule.BackendRefs) { + case 0: + panic("not possible to have a tcp route rule with no backend refs") + case 1: + tcpBackendRef := routeRule.BackendRefs[0] + + clusterName := b.backendTargetToClusterName(tcpBackendRef.BackendTarget, targets, defaultDC) + + rb := lb.addL4RouterForDirect(clusterName, statPrefix) + if destination.Explicit == nil { + rb.addIPAndPortMatch(destination.VirtualIPs, virtualPortNumber) + } + rb.buildRouter() + default: + clusters := make([]*pbproxystate.L4WeightedDestinationCluster, 0, len(routeRule.BackendRefs)) + for _, tcpBackendRef := range routeRule.BackendRefs { + clusterName := b.backendTargetToClusterName(tcpBackendRef.BackendTarget, targets, defaultDC) + + clusters = append(clusters, &pbproxystate.L4WeightedDestinationCluster{ + Name: clusterName, + Weight: wrapperspb.UInt32(tcpBackendRef.Weight), + }) + } + + rb := lb.addL4RouterForSplit(clusters, statPrefix) + if destination.Explicit == nil { + rb.addIPAndPortMatch(destination.VirtualIPs, virtualPortNumber) + } + rb.buildRouter() + } + } + + if useRDS { + if !isProtocolHTTPLike(effectiveProtocol) { + panic(fmt.Sprintf("it should not be possible to have a tcp protocol here: %v", effectiveProtocol)) } + + rb := lb.addL7Router("", effectiveProtocol) + if destination.Explicit == nil { + rb.addIPMatch(destination.VirtualIPs) + } + rb.buildRouter() + } else { + if isProtocolHTTPLike(effectiveProtocol) { + panic(fmt.Sprintf("it should not be possible to have an http-like protocol here: %v", effectiveProtocol)) + } + } + + lb.buildListener() + + if needsNullRouteCluster { + b.addNullRouteCluster() + } + + for _, details := range targets { + dc := defaultDC(details.BackendRef.Datacenter) + portName := details.BackendRef.Port + + sni := DestinationSNI( + details.BackendRef.Ref, + dc, + b.trustDomain, + ) + clusterName := fmt.Sprintf("%s.%s", portName, sni) + + b.addCluster(clusterName, sni, portName, details.IdentityRefs) + b.addEndpointsRef(clusterName, details.ServiceEndpointsId, details.MeshPort) } return b } -// buildExplicitDestination creates listeners, routers, clusters, and endpointRefs for an explicit destination -// and adds them to the proxyState. -func (b *Builder) buildExplicitDestination(destination *intermediate.Destination) *Builder { - serviceRef := destination.Explicit.DestinationRef - sni := DestinationSNI(serviceRef, b.localDatacenter, b.trustDomain) - portInfo := newServicePortInfo(destination.ServiceEndpoints.Endpoints) - - return b.addExplicitOutboundListener(destination.Explicit). - addEndpointsRef(sni, destination.ServiceEndpoints.Resource.Id, portInfo.meshPortName). - addRouters(portInfo, destination, serviceRef, sni, b.localDatacenter, false). - addClusters(portInfo, destination, sni) +const NullRouteClusterName = "null_route_cluster" + +func (b *Builder) addNullRouteCluster() *Builder { + cluster := &pbproxystate.Cluster{ + Name: NullRouteClusterName, + Group: &pbproxystate.Cluster_EndpointGroup{ + EndpointGroup: &pbproxystate.EndpointGroup{ + Group: &pbproxystate.EndpointGroup_Static{ + Static: &pbproxystate.StaticEndpointGroup{ + Config: &pbproxystate.StaticEndpointGroupConfig{ + ConnectTimeout: durationpb.New(10 * time.Second), + }, + }, + }, + }, + }, + } + + b.proxyStateTemplate.ProxyState.Clusters[cluster.Name] = cluster + return b } -// buildImplicitDestination creates listeners, routers, clusters, and endpointRefs for an implicit destination -// and adds them to the proxyState. -func (b *Builder) buildImplicitDestination(destination *intermediate.Destination) *Builder { - serviceRef := resource.Reference(destination.ServiceEndpoints.Resource.Owner, "") - sni := DestinationSNI(serviceRef, b.localDatacenter, b.trustDomain) - portInfo := newServicePortInfo(destination.ServiceEndpoints.Endpoints) - - return b.addEndpointsRef(sni, destination.ServiceEndpoints.Resource.Id, portInfo.meshPortName). - addRouters(portInfo, destination, serviceRef, sni, b.localDatacenter, true). - addClusters(portInfo, destination, sni) +func (b *ListenerBuilder) addL4RouterForDirect(clusterName, statPrefix string) *RouterBuilder { + // For explicit destinations, we have no filter chain match, and filters + // are based on port protocol. + router := &pbproxystate.Router{} + + if statPrefix == "" { + statPrefix = "upstream." + } + + router.Destination = &pbproxystate.Router_L4{ + L4: &pbproxystate.L4Destination{ + Destination: &pbproxystate.L4Destination_Cluster{ + Cluster: &pbproxystate.DestinationCluster{ + Name: clusterName, + }, + }, + StatPrefix: statPrefix, + }, + } + + return b.NewRouterBuilder(router) } -// addClusters creates clusters for each service port in the pre-processed a servicePortInfo. -func (b *Builder) addClusters(portInfo *servicePortInfo, destination *intermediate.Destination, sni string) *Builder { - for portName, port := range portInfo.servicePorts { - if port.GetProtocol() != pbcatalog.Protocol_PROTOCOL_TCP { - //only implementing L4 at the moment - } else { - clusterName := fmt.Sprintf("%s.%s", portName, sni) - b.addCluster(clusterName, sni, portName, destination.Identities) - } +func (b *ListenerBuilder) addL4RouterForSplit( + clusters []*pbproxystate.L4WeightedDestinationCluster, + statPrefix string, +) *RouterBuilder { + // For explicit destinations, we have no filter chain match, and filters + // are based on port protocol. + router := &pbproxystate.Router{} + + if statPrefix == "" { + statPrefix = "upstream." } - return b + + router.Destination = &pbproxystate.Router_L4{ + L4: &pbproxystate.L4Destination{ + Destination: &pbproxystate.L4Destination_WeightedClusters{ + WeightedClusters: &pbproxystate.L4WeightedClusterGroup{ + Clusters: clusters, + }, + }, + StatPrefix: statPrefix, + // TODO: can we use RDS for TCPRoute split? + }, + } + + return b.NewRouterBuilder(router) } -// addRouters creates routers for each service port in the pre-processed a servicePortInfo. -func (b *Builder) addRouters(portInfo *servicePortInfo, destination *intermediate.Destination, - serviceRef *pbresource.Reference, sni, datacenter string, isImplicitDestination bool) *Builder { +func (b *ListenerBuilder) addL7Router(statPrefix string, protocol pbcatalog.Protocol) *RouterBuilder { + // For explicit destinations, we have no filter chain match, and filters + // are based on port protocol. + router := &pbproxystate.Router{} - for portName, port := range portInfo.servicePorts { - statPrefix := DestinationStatPrefix(serviceRef, portName, datacenter) + listenerName := b.listener.Name + if listenerName == "" { + panic("listenerName is required") + } - if port.GetProtocol() != pbcatalog.Protocol_PROTOCOL_TCP { - //only implementing L4 at the moment - continue - } + if statPrefix == "" { + statPrefix = "upstream." + } - clusterName := fmt.Sprintf("%s.%s", portName, sni) - var portForRouterMatch *pbcatalog.WorkloadPort - // router matches based on destination ports should only occur on implicit destinations - // for explicit, nil will get passed to addRouterWithIPAndPortMatch() which will then - // exclude the destinationPort match on the listener router. - if isImplicitDestination { - portForRouterMatch = port - } - b.addRouterWithIPAndPortMatch(clusterName, statPrefix, portForRouterMatch, destination.VirtualIPs) + if !isProtocolHTTPLike(protocol) { + panic(fmt.Sprintf("unexpected protocol: %v", protocol)) } - return b + + router.Destination = &pbproxystate.Router_L7{ + L7: &pbproxystate.L7Destination{ + Name: listenerName, + StatPrefix: statPrefix, + StaticRoute: false, + }, + } + + return b.NewRouterBuilder(router) } // addExplicitOutboundListener creates an outbound listener for an explicit destination. -func (b *Builder) addExplicitOutboundListener(explicit *pbmesh.Upstream) *Builder { +func (b *Builder) addExplicitOutboundListener(explicit *pbmesh.Upstream) *ListenerBuilder { + listener := makeExplicitListener(explicit, pbproxystate.Direction_DIRECTION_OUTBOUND) + + return b.NewListenerBuilder(listener) +} + +func makeExplicitListener(explicit *pbmesh.Upstream, direction pbproxystate.Direction) *pbproxystate.Listener { + if explicit == nil { + panic("explicit upstream required") + } + listener := &pbproxystate.Listener{ - Direction: pbproxystate.Direction_DIRECTION_OUTBOUND, + Direction: direction, } + // TODO(v2): access logs, connection balancing + // Create outbound listener address. switch explicit.ListenAddr.(type) { case *pbmesh.Upstream_IpPort: @@ -128,11 +413,11 @@ func (b *Builder) addExplicitOutboundListener(explicit *pbmesh.Upstream) *Builde listener.Name = DestinationListenerName(explicit.DestinationRef.Name, explicit.DestinationPort, destinationAddr.Unix.Path, 0) } - return b.NewListenerBuilder(listener).buildListener() + return listener } // addTransparentProxyOutboundListener creates an outbound listener for transparent proxy mode. -func (b *Builder) addTransparentProxyOutboundListener(port uint32) *Builder { +func (b *Builder) addTransparentProxyOutboundListener(port uint32) *ListenerBuilder { listener := &pbproxystate.Listener{ Name: xdscommon.OutboundListenerName, Direction: pbproxystate.Direction_DIRECTION_OUTBOUND, @@ -145,63 +430,49 @@ func (b *Builder) addTransparentProxyOutboundListener(port uint32) *Builder { Capabilities: []pbproxystate.Capability{pbproxystate.Capability_CAPABILITY_TRANSPARENT}, } - return b.NewListenerBuilder(listener).buildListener() + return b.NewListenerBuilder(listener) } -// addRouterDestination returns the appropriate router destination based on the port protocol. -func (b *Builder) addRouterDestination(router *pbproxystate.Router, clusterName, statPrefix string, _ *pbcatalog.WorkloadPort) *Builder { - //switch port.GetProtocol() { - //case pbcatalog.Protocol_PROTOCOL_TCP: - // router.Destination = &pbproxystate.Router_L4{ - // L4: &pbproxystate.L4Destination{ - // Name: clusterName, - // StatPrefix: statPrefix, - // }, - // } - //case pbcatalog.Protocol_PROTOCOL_HTTP: - // router.Destination = &pbproxystate.Router_L7{ - // L7: &pbproxystate.L7Destination{ - // Name: clusterName, - // StatPrefix: statPrefix, - // }, - // } - //} - // TODO(proxystate): add L7 in future work. - router.Destination = &pbproxystate.Router_L4{ - L4: &pbproxystate.L4Destination{ - Name: clusterName, - StatPrefix: statPrefix, - }, +func isProtocolHTTPLike(protocol pbcatalog.Protocol) bool { + // enumcover:pbcatalog.Protocol + switch protocol { + case pbcatalog.Protocol_PROTOCOL_TCP: + return false + case pbcatalog.Protocol_PROTOCOL_HTTP2, + pbcatalog.Protocol_PROTOCOL_HTTP, + pbcatalog.Protocol_PROTOCOL_GRPC: + return true + case pbcatalog.Protocol_PROTOCOL_MESH: + fallthrough // to default + case pbcatalog.Protocol_PROTOCOL_UNSPECIFIED: + fallthrough // to default + default: + return false } - return b } -// addRouterWithIPAndPortMatch will create and add a listener router to proxyState that -// matches on the IP and port of the cluster. -func (b *Builder) addRouterWithIPAndPortMatch(clusterName, statPrefix string, port *pbcatalog.WorkloadPort, vips []string) *Builder { - listener := b.getLastBuiltListener() +func (b *RouterBuilder) addIPMatch(vips []string) *RouterBuilder { + return b.addIPAndPortMatch(vips, 0) +} - // For explicit destinations, we have no filter chain match, and filters are based on port protocol. - router := &pbproxystate.Router{} - b.addRouterDestination(router, clusterName, statPrefix, port) +func (b *RouterBuilder) addIPAndPortMatch(vips []string, virtualPort uint32) *RouterBuilder { + b.router.Match = makeRouterMatchForIPAndPort(vips, virtualPort) + return b +} - if router.Destination != nil { - if (port != nil || len(vips) > 0) && router.Match == nil { - router.Match = &pbproxystate.Match{} - } - if port != nil { - router.Match.DestinationPort = &wrapperspb.UInt32Value{Value: port.GetPort()} - } - for _, vip := range vips { - router.Match.PrefixRanges = append(router.Match.PrefixRanges, &pbproxystate.CidrRange{ - AddressPrefix: vip, - PrefixLen: &wrapperspb.UInt32Value{Value: 32}, - }) +func makeRouterMatchForIPAndPort(vips []string, virtualPort uint32) *pbproxystate.Match { + match := &pbproxystate.Match{} + for _, vip := range vips { + match.PrefixRanges = append(match.PrefixRanges, &pbproxystate.CidrRange{ + AddressPrefix: vip, + PrefixLen: &wrapperspb.UInt32Value{Value: 32}, + }) + + if virtualPort > 0 { + match.DestinationPort = &wrapperspb.UInt32Value{Value: virtualPort} } - listener.Routers = append(listener.Routers, router) } - - return b + return match } // addCluster creates and adds a cluster to the proxyState based on the destination. @@ -211,8 +482,14 @@ func (b *Builder) addCluster(clusterName, sni, portName string, destinationIdent spiffeIDs = append(spiffeIDs, connect.SpiffeIDFromIdentityRef(b.trustDomain, identity)) } + // TODO(v2): DestinationPolicy: connect timeout, lb policy, cluster discovery type, circuit breakers, outlier detection + + // TODO(v2): if http2/grpc then set http2protocol options + // Create destination cluster. cluster := &pbproxystate.Cluster{ + Name: clusterName, + AltStatName: clusterName, Group: &pbproxystate.Cluster_EndpointGroup{ EndpointGroup: &pbproxystate.EndpointGroup{ Group: &pbproxystate.EndpointGroup_Dynamic{ @@ -238,11 +515,15 @@ func (b *Builder) addCluster(clusterName, sni, portName string, destinationIdent }, } - b.proxyStateTemplate.ProxyState.Clusters[clusterName] = cluster + b.proxyStateTemplate.ProxyState.Clusters[cluster.Name] = cluster return b } +func (b *Builder) addRoute(listenerName string, route *pbproxystate.Route) { + b.proxyStateTemplate.ProxyState.Routes[listenerName] = route +} + // addEndpointsRef creates and add an endpointRef for each serviceEndpoint for a destination and // adds it to the proxyStateTemplate so it will be processed later during reconciliation by // the XDS controller. @@ -254,8 +535,9 @@ func (b *Builder) addEndpointsRef(clusterName string, serviceEndpointsID *pbreso return b } -// last -func (b *Builder) getLastBuiltListener() *pbproxystate.Listener { - lastBuiltIndex := len(b.proxyStateTemplate.ProxyState.Listeners) - 1 - return b.proxyStateTemplate.ProxyState.Listeners[lastBuiltIndex] +func orDefault(v, def string) string { + if v != "" { + return v + } + return def } diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/destination_builder_multiport_test.go b/internal/mesh/internal/controllers/sidecarproxy/builder/destination_builder_multiport_test.go index 1bd90fcbc63c..1443acc63255 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/destination_builder_multiport_test.go +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/destination_builder_multiport_test.go @@ -5,22 +5,27 @@ package builder import ( "fmt" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/testing/golden" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" "sort" "testing" "github.com/stretchr/testify/require" "github.com/hashicorp/consul/internal/catalog" + "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/routestest" + "github.com/hashicorp/consul/internal/mesh/internal/types" "github.com/hashicorp/consul/internal/mesh/internal/types/intermediate" + "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/internal/testing/golden" + pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" "github.com/hashicorp/consul/proto-public/pbresource" ) func TestBuildMultiportImplicitDestinations(t *testing.T) { + // TODO(rb/v2): add a fetchertest package to construct implicit upstreams + // correctly from inputs. the following is far too manual and error prone + // to be an accurate representation of what implicit upstreams look like. const ( apiApp = "api-app" apiApp2 = "api-app2" @@ -50,18 +55,55 @@ func TestBuildMultiportImplicitDestinations(t *testing.T) { }, }, } + apiAppService := resourcetest.Resource(catalog.ServiceType, apiApp). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, serviceData). + Build() + + apiApp2Service := resourcetest.Resource(catalog.ServiceType, apiApp2). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, serviceData). + Build() + apiAppEndpoints := resourcetest.Resource(catalog.ServiceEndpointsType, apiApp). - WithOwner(resourcetest.Resource(catalog.ServiceType, apiApp). - WithTenancy(resource.DefaultNamespacedTenancy()).ID()). + WithOwner(apiAppService.Id). WithData(t, multiportEndpointsData). WithTenancy(resource.DefaultNamespacedTenancy()).Build() apiApp2Endpoints := resourcetest.Resource(catalog.ServiceEndpointsType, apiApp2). - WithOwner(resourcetest.Resource(catalog.ServiceType, apiApp2). - WithTenancy(resource.DefaultNamespacedTenancy()).ID()). + WithOwner(apiApp2Service.Id). WithData(t, multiportEndpointsData). WithTenancy(resource.DefaultNamespacedTenancy()).Build() + mwEndpointsData := &pbcatalog.ServiceEndpoints{ // variant on apiAppEndpoints + Endpoints: []*pbcatalog.Endpoint{ + { + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "10.0.0.1"}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "admin-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, + "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, + "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + }, + { + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "10.0.0.2"}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "admin-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, + "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, + "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + }, + }, + } + mwEndpoints := resourcetest.Resource(catalog.ServiceEndpointsType, apiApp). + WithOwner(apiAppService.Id). + WithData(t, mwEndpointsData). + WithTenancy(resource.DefaultNamespacedTenancy()).Build() + apiAppIdentity := &pbresource.Reference{ Name: fmt.Sprintf("%s-identity", apiApp), Tenancy: apiAppEndpoints.Id.Tenancy, @@ -72,85 +114,97 @@ func TestBuildMultiportImplicitDestinations(t *testing.T) { Tenancy: apiApp2Endpoints.Id.Tenancy, } - destination1 := &intermediate.Destination{ - ServiceEndpoints: &intermediate.ServiceEndpoints{ - Resource: apiAppEndpoints, - Endpoints: multiportEndpointsData, - }, - Identities: []*pbresource.Reference{apiAppIdentity}, - VirtualIPs: []string{"1.1.1.1"}, - } + apiAppComputedRoutesID := resource.ReplaceType(types.ComputedRoutesType, apiAppService.Id) + apiAppComputedRoutes := routestest.BuildComputedRoutes(t, apiAppComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](t, apiAppService), + ) + require.NotNil(t, apiAppComputedRoutes) - destination2 := &intermediate.Destination{ - ServiceEndpoints: &intermediate.ServiceEndpoints{ - Resource: apiApp2Endpoints, - Endpoints: multiportEndpointsData, - }, - Identities: []*pbresource.Reference{apiApp2Identity}, - VirtualIPs: []string{"2.2.2.2", "3.3.3.3"}, + apiApp2ComputedRoutesID := resource.ReplaceType(types.ComputedRoutesType, apiApp2Service.Id) + apiApp2ComputedRoutes := routestest.BuildComputedRoutes(t, apiApp2ComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](t, apiApp2Service), + ) + require.NotNil(t, apiApp2ComputedRoutes) + + newImplicitDestination := func( + svc *pbresource.Resource, + endpoints *pbresource.Resource, + computedRoutes *types.DecodedComputedRoutes, + identities []*pbresource.Reference, + virtualIPs []string, + ) []*intermediate.Destination { + svcDec := resourcetest.MustDecode[*pbcatalog.Service](t, svc) + seDec := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](t, endpoints) + + var out []*intermediate.Destination + for _, port := range svcDec.Data.Ports { + portName := port.TargetPort + if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { + continue + } + + portConfig, ok := computedRoutes.Data.PortedConfigs[portName] + require.True(t, ok, "port %q not found in port configs", portName) + + dest := &intermediate.Destination{ + Service: svcDec, + ComputedPortRoutes: routestest.MutateTarget(t, portConfig, svc.Id, portName, func(details *pbmesh.BackendTargetDetails) { + details.ServiceEndpointsId = endpoints.Id + details.ServiceEndpoints = seDec.Data + details.IdentityRefs = identities + }), + VirtualIPs: virtualIPs, + } + out = append(out, dest) + } + return out } + apiAppDestinations := newImplicitDestination( + apiAppService, + apiAppEndpoints, + apiAppComputedRoutes, + []*pbresource.Reference{apiAppIdentity}, + []string{"1.1.1.1"}, + ) + + apiApp2Destinations := newImplicitDestination( + apiApp2Service, + apiApp2Endpoints, + apiApp2ComputedRoutes, + []*pbresource.Reference{apiApp2Identity}, + []string{"2.2.2.2", "3.3.3.3"}, + ) + + mwDestinations := newImplicitDestination( + apiAppService, + mwEndpoints, + apiAppComputedRoutes, + []*pbresource.Reference{apiAppIdentity}, + []string{"1.1.1.1"}, + ) + + twoImplicitDestinations := append( + append([]*intermediate.Destination{}, apiAppDestinations...), + apiApp2Destinations..., + ) + cases := map[string]struct { getDestinations func() []*intermediate.Destination }{ // Most basic test that multiport configuration works "destination/multiport-l4-single-implicit-destination-tproxy": { - getDestinations: func() []*intermediate.Destination { return []*intermediate.Destination{destination1} }, + getDestinations: func() []*intermediate.Destination { return apiAppDestinations }, }, // Test shows that with multiple workloads for a service exposing the same ports, the routers // and clusters do not get duplicated. "destination/multiport-l4-single-implicit-destination-with-multiple-workloads-tproxy": { - getDestinations: func() []*intermediate.Destination { - mwEndpointsData := &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "10.0.0.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "admin-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - { - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "10.0.0.2"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "admin-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - } - mwEndpoints := resourcetest.Resource(catalog.ServiceEndpointsType, apiApp). - WithOwner(resourcetest.Resource(catalog.ServiceType, apiApp). - WithTenancy(resource.DefaultNamespacedTenancy()).ID()). - WithData(t, mwEndpointsData). - WithTenancy(resource.DefaultNamespacedTenancy()).Build() - - mwIdentity := &pbresource.Reference{ - Name: fmt.Sprintf("%s-identity", apiApp), - Tenancy: mwEndpoints.Id.Tenancy, - } - - mwDestination := &intermediate.Destination{ - ServiceEndpoints: &intermediate.ServiceEndpoints{ - Resource: mwEndpoints, - Endpoints: mwEndpointsData, - }, - Identities: []*pbresource.Reference{mwIdentity}, - VirtualIPs: []string{"1.1.1.1"}, - } - return []*intermediate.Destination{mwDestination} - }, + getDestinations: func() []*intermediate.Destination { return mwDestinations }, }, // Test shows that with multiple workloads for a service exposing the same ports, the routers // and clusters do not get duplicated. "destination/multiport-l4-multiple-implicit-destinations-tproxy": { - getDestinations: func() []*intermediate.Destination { return []*intermediate.Destination{destination1, destination2} }, + getDestinations: func() []*intermediate.Destination { return twoImplicitDestinations }, }, } diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/destination_builder_test.go b/internal/mesh/internal/controllers/sidecarproxy/builder/destination_builder_test.go index 74fd5666c992..a2381da05d6c 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/destination_builder_test.go +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/destination_builder_test.go @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/require" "github.com/hashicorp/consul/internal/catalog" + "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/routestest" + "github.com/hashicorp/consul/internal/mesh/internal/types" "github.com/hashicorp/consul/internal/mesh/internal/types/intermediate" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/resourcetest" @@ -33,14 +35,53 @@ var ( }, }, } + + serviceData = &pbcatalog.Service{ + Ports: []*pbcatalog.ServicePort{ + { + TargetPort: "tcp", + VirtualPort: 8080, + Protocol: pbcatalog.Protocol_PROTOCOL_TCP, + }, + { + TargetPort: "http", + VirtualPort: 8080, + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, + }, + { + TargetPort: "mesh", + VirtualPort: 20000, + Protocol: pbcatalog.Protocol_PROTOCOL_MESH, + }, + }, + } ) func TestBuildExplicitDestinations(t *testing.T) { + api1Service := resourcetest.Resource(catalog.ServiceType, "api-1"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, serviceData). + Build() + + api2Service := resourcetest.Resource(catalog.ServiceType, "api-2"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, serviceData). + Build() + + api3Service := resourcetest.Resource(catalog.ServiceType, "api-3"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, serviceData). + Build() + api1Endpoints := resourcetest.Resource(catalog.ServiceEndpointsType, "api-1"). - WithData(t, endpointsData).WithTenancy(resource.DefaultNamespacedTenancy()).Build() + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, endpointsData). + Build() api2Endpoints := resourcetest.Resource(catalog.ServiceEndpointsType, "api-2"). - WithData(t, endpointsData).WithTenancy(resource.DefaultNamespacedTenancy()).Build() + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, endpointsData). + Build() api1Identity := &pbresource.Reference{ Name: "api1-identity", @@ -52,6 +93,86 @@ func TestBuildExplicitDestinations(t *testing.T) { Tenancy: api2Endpoints.Id.Tenancy, } + api1HTTPRoute := resourcetest.Resource(types.HTTPRouteType, "api-1-http-route"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, &pbmesh.HTTPRoute{ + ParentRefs: []*pbmesh.ParentReference{{ + Ref: resource.Reference(api1Service.Id, ""), + Port: "http", + }}, + Rules: []*pbmesh.HTTPRouteRule{{ + BackendRefs: []*pbmesh.HTTPBackendRef{ + { + BackendRef: &pbmesh.BackendReference{ + Ref: resource.Reference(api2Service.Id, ""), + }, + Weight: 60, + }, + { + BackendRef: &pbmesh.BackendReference{ + Ref: resource.Reference(api1Service.Id, ""), + }, + Weight: 40, + }, + { + BackendRef: &pbmesh.BackendReference{ + Ref: resource.Reference(api3Service.Id, ""), + }, + Weight: 10, + }, + }, + }}, + }). + Build() + + api1TCPRoute := resourcetest.Resource(types.TCPRouteType, "api-1-tcp-route"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, &pbmesh.TCPRoute{ + ParentRefs: []*pbmesh.ParentReference{{ + Ref: resource.Reference(api1Service.Id, ""), + Port: "tcp", + }}, + Rules: []*pbmesh.TCPRouteRule{{ + BackendRefs: []*pbmesh.TCPBackendRef{ + { + BackendRef: &pbmesh.BackendReference{ + Ref: resource.Reference(api2Service.Id, ""), + }, + Weight: 60, + }, + { + BackendRef: &pbmesh.BackendReference{ + Ref: resource.Reference(api1Service.Id, ""), + }, + Weight: 40, + }, + { + BackendRef: &pbmesh.BackendReference{ + Ref: resource.Reference(api3Service.Id, ""), + }, + Weight: 10, + }, + }, + }}, + }). + Build() + + api1ComputedRoutesID := resource.ReplaceType(types.ComputedRoutesType, api1Service.Id) + api1ComputedRoutes := routestest.BuildComputedRoutes(t, api1ComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](t, api1Service), + resourcetest.MustDecode[*pbcatalog.Service](t, api2Service), + // notably we do NOT include api3Service here so we trigger a null route to be generated + resourcetest.MustDecode[*pbmesh.HTTPRoute](t, api1HTTPRoute), + resourcetest.MustDecode[*pbmesh.TCPRoute](t, api1TCPRoute), + ) + require.NotNil(t, api1ComputedRoutes) + + api2ComputedRoutesID := resource.ReplaceType(types.ComputedRoutesType, api2Service.Id) + api2ComputedRoutes := routestest.BuildComputedRoutes(t, api2ComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](t, api2Service), + ) + require.NotNil(t, api2ComputedRoutes) + destinationIpPort := &intermediate.Destination{ Explicit: &pbmesh.Upstream{ DestinationRef: resource.Reference(api1Endpoints.Id, ""), @@ -61,11 +182,12 @@ func TestBuildExplicitDestinations(t *testing.T) { IpPort: &pbmesh.IPPortAddress{Ip: "1.1.1.1", Port: 1234}, }, }, - ServiceEndpoints: &intermediate.ServiceEndpoints{ - Resource: api1Endpoints, - Endpoints: endpointsData, - }, - Identities: []*pbresource.Reference{api1Identity}, + Service: resourcetest.MustDecode[*pbcatalog.Service](t, api1Service), + ComputedPortRoutes: routestest.MutateTarget(t, api1ComputedRoutes.Data.PortedConfigs["tcp"], api1Service.Id, "tcp", func(details *pbmesh.BackendTargetDetails) { + details.ServiceEndpointsId = api1Endpoints.Id + details.ServiceEndpoints = endpointsData + details.IdentityRefs = []*pbresource.Reference{api1Identity} + }), } destinationUnix := &intermediate.Destination{ @@ -77,11 +199,29 @@ func TestBuildExplicitDestinations(t *testing.T) { Unix: &pbmesh.UnixSocketAddress{Path: "/path/to/socket", Mode: "0666"}, }, }, - ServiceEndpoints: &intermediate.ServiceEndpoints{ - Resource: api2Endpoints, - Endpoints: endpointsData, + Service: resourcetest.MustDecode[*pbcatalog.Service](t, api2Service), + ComputedPortRoutes: routestest.MutateTarget(t, api2ComputedRoutes.Data.PortedConfigs["tcp"], api2Service.Id, "tcp", func(details *pbmesh.BackendTargetDetails) { + details.ServiceEndpointsId = api2Endpoints.Id + details.ServiceEndpoints = endpointsData + details.IdentityRefs = []*pbresource.Reference{api2Identity} + }), + } + + destinationIpPortHTTP := &intermediate.Destination{ + Explicit: &pbmesh.Upstream{ + DestinationRef: resource.Reference(api1Endpoints.Id, ""), + DestinationPort: "http", + Datacenter: "dc1", + ListenAddr: &pbmesh.Upstream_IpPort{ + IpPort: &pbmesh.IPPortAddress{Ip: "1.1.1.1", Port: 1234}, + }, }, - Identities: []*pbresource.Reference{api2Identity}, + Service: resourcetest.MustDecode[*pbcatalog.Service](t, api1Service), + ComputedPortRoutes: routestest.MutateTarget(t, api1ComputedRoutes.Data.PortedConfigs["http"], api1Service.Id, "http", func(details *pbmesh.BackendTargetDetails) { + details.ServiceEndpointsId = api1Endpoints.Id + details.ServiceEndpoints = endpointsData + details.IdentityRefs = []*pbresource.Reference{api1Identity} + }), } cases := map[string]struct { @@ -96,11 +236,13 @@ func TestBuildExplicitDestinations(t *testing.T) { "destination/l4-multi-destination": { destinations: []*intermediate.Destination{destinationIpPort, destinationUnix}, }, + "destination/mixed-multi-destination": { + destinations: []*intermediate.Destination{destinationIpPort, destinationUnix, destinationIpPortHTTP}, + }, } for name, c := range cases { t.Run(name, func(t *testing.T) { - proxyTmpl := New(testProxyStateTemplateID(), testIdentityRef(), "foo.consul", "dc1", nil). BuildDestinations(c.destinations). Build() @@ -114,16 +256,23 @@ func TestBuildExplicitDestinations(t *testing.T) { } func TestBuildImplicitDestinations(t *testing.T) { + api1Service := resourcetest.Resource(catalog.ServiceType, "api-1"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, serviceData). + Build() + + api2Service := resourcetest.Resource(catalog.ServiceType, "api-2"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, serviceData). + Build() + api1Endpoints := resourcetest.Resource(catalog.ServiceEndpointsType, "api-1"). - WithOwner( - resourcetest.Resource(catalog.ServiceType, "api-1"). - WithTenancy(resource.DefaultNamespacedTenancy()).ID()). + WithOwner(api1Service.Id). WithTenancy(resource.DefaultNamespacedTenancy()). WithData(t, endpointsData).Build() api2Endpoints := resourcetest.Resource(catalog.ServiceEndpointsType, "api-2"). - WithOwner(resourcetest.Resource(catalog.ServiceType, "api-2"). - WithTenancy(resource.DefaultNamespacedTenancy()).ID()). + WithOwner(api2Service.Id). WithTenancy(resource.DefaultNamespacedTenancy()). WithData(t, endpointsData).Build() @@ -137,6 +286,18 @@ func TestBuildImplicitDestinations(t *testing.T) { Tenancy: api2Endpoints.Id.Tenancy, } + api1ComputedRoutesID := resource.ReplaceType(types.ComputedRoutesType, api1Service.Id) + api1ComputedRoutes := routestest.BuildComputedRoutes(t, api1ComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](t, api1Service), + ) + require.NotNil(t, api1ComputedRoutes) + + api2ComputedRoutesID := resource.ReplaceType(types.ComputedRoutesType, api2Service.Id) + api2ComputedRoutes := routestest.BuildComputedRoutes(t, api2ComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](t, api2Service), + ) + require.NotNil(t, api2ComputedRoutes) + proxyCfg := &pbmesh.ProxyConfiguration{ DynamicConfig: &pbmesh.DynamicConfig{ Mode: pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT, @@ -147,20 +308,22 @@ func TestBuildImplicitDestinations(t *testing.T) { } destination1 := &intermediate.Destination{ - ServiceEndpoints: &intermediate.ServiceEndpoints{ - Resource: api1Endpoints, - Endpoints: endpointsData, - }, - Identities: []*pbresource.Reference{api1Identity}, + Service: resourcetest.MustDecode[*pbcatalog.Service](t, api1Service), + ComputedPortRoutes: routestest.MutateTarget(t, api1ComputedRoutes.Data.PortedConfigs["tcp"], api1Service.Id, "tcp", func(details *pbmesh.BackendTargetDetails) { + details.ServiceEndpointsId = api1Endpoints.Id + details.ServiceEndpoints = endpointsData + details.IdentityRefs = []*pbresource.Reference{api1Identity} + }), VirtualIPs: []string{"1.1.1.1"}, } destination2 := &intermediate.Destination{ - ServiceEndpoints: &intermediate.ServiceEndpoints{ - Resource: api2Endpoints, - Endpoints: endpointsData, - }, - Identities: []*pbresource.Reference{api2Identity}, + Service: resourcetest.MustDecode[*pbcatalog.Service](t, api2Service), + ComputedPortRoutes: routestest.MutateTarget(t, api2ComputedRoutes.Data.PortedConfigs["tcp"], api2Service.Id, "tcp", func(details *pbmesh.BackendTargetDetails) { + details.ServiceEndpointsId = api2Endpoints.Id + details.ServiceEndpoints = endpointsData + details.IdentityRefs = []*pbresource.Reference{api2Identity} + }), VirtualIPs: []string{"2.2.2.2", "3.3.3.3"}, } @@ -173,11 +336,12 @@ func TestBuildImplicitDestinations(t *testing.T) { IpPort: &pbmesh.IPPortAddress{Ip: "1.1.1.1", Port: 1234}, }, }, - ServiceEndpoints: &intermediate.ServiceEndpoints{ - Resource: api1Endpoints, - Endpoints: endpointsData, - }, - Identities: []*pbresource.Reference{api1Identity}, + Service: resourcetest.MustDecode[*pbcatalog.Service](t, api1Service), + ComputedPortRoutes: routestest.MutateTarget(t, api1ComputedRoutes.Data.PortedConfigs["tcp"], api1Service.Id, "tcp", func(details *pbmesh.BackendTargetDetails) { + details.ServiceEndpointsId = api1Endpoints.Id + details.ServiceEndpoints = endpointsData + details.IdentityRefs = []*pbresource.Reference{api1Identity} + }), } cases := map[string]struct { @@ -207,36 +371,3 @@ func TestBuildImplicitDestinations(t *testing.T) { }) } } - -func Test_isMeshPort(t *testing.T) { - cases := map[string]struct { - protocol pbcatalog.Protocol - expectedResult bool - }{ - "mesh protocol returns true": { - protocol: pbcatalog.Protocol_PROTOCOL_MESH, - expectedResult: true, - }, - "grpc protocol returns false": { - protocol: pbcatalog.Protocol_PROTOCOL_GRPC, - expectedResult: false, - }, - "tcp protocol returns false": { - protocol: pbcatalog.Protocol_PROTOCOL_TCP, - expectedResult: false, - }, - "http protocol returns false": { - protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - expectedResult: false, - }, - "http2 protocol returns false": { - protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, - expectedResult: false, - }, - } - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - require.Equal(t, tc.expectedResult, isMeshPort(&pbcatalog.WorkloadPort{Protocol: tc.protocol})) - }) - } -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/local_app.go b/internal/mesh/internal/controllers/sidecarproxy/builder/local_app.go index 3cd02250c086..409f50363816 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/local_app.go +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/local_app.go @@ -86,7 +86,11 @@ func (l *ListenerBuilder) addInboundRouter(clusterName string, port *pbcatalog.W r := &pbproxystate.Router{ Destination: &pbproxystate.Router_L4{ L4: &pbproxystate.L4Destination{ - Name: clusterName, + Destination: &pbproxystate.L4Destination_Cluster{ + Cluster: &pbproxystate.DestinationCluster{ + Name: clusterName, + }, + }, StatPrefix: l.listener.Name, }, }, diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/routes.go b/internal/mesh/internal/controllers/sidecarproxy/builder/routes.go new file mode 100644 index 000000000000..c8cb9e2fd10d --- /dev/null +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/routes.go @@ -0,0 +1,320 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package builder + +import ( + "fmt" + "strings" + + "google.golang.org/protobuf/types/known/wrapperspb" + + "github.com/hashicorp/consul/internal/mesh/internal/types" + pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" +) + +func (b *Builder) backendTargetToClusterName( + backendTarget string, + targets map[string]*pbmesh.BackendTargetDetails, + defaultDC func(string) string, +) string { + if backendTarget == types.NullRouteBackend { + return NullRouteClusterName + } + + details, ok := targets[backendTarget] + if !ok { + panic("dangling reference") + } + + backendRef := details.BackendRef + + dc := defaultDC(backendRef.Datacenter) + + sni := DestinationSNI( + details.BackendRef.Ref, + dc, + b.trustDomain, + ) + + return fmt.Sprintf("%s.%s", details.BackendRef.Port, sni) +} + +func (b *Builder) makeHTTPRouteDestination( + computedBackendRefs []*pbmesh.ComputedHTTPBackendRef, + destConfig *pbproxystate.DestinationConfiguration, + targets map[string]*pbmesh.BackendTargetDetails, + defaultDC func(string) string, +) *pbproxystate.RouteDestination { + switch len(computedBackendRefs) { + case 0: + panic("not possible to have a route rule with no backend refs") + case 1: + return b.makeRouteDestinationForDirect(computedBackendRefs[0].BackendTarget, destConfig, targets, defaultDC) + default: + clusters := make([]*pbproxystate.L7WeightedDestinationCluster, 0, len(computedBackendRefs)) + for _, computedBackendRef := range computedBackendRefs { + clusterName := b.backendTargetToClusterName(computedBackendRef.BackendTarget, targets, defaultDC) + + clusters = append(clusters, &pbproxystate.L7WeightedDestinationCluster{ + Name: clusterName, + Weight: &wrapperspb.UInt32Value{ + Value: computedBackendRef.Weight, + }, + }) + } + return b.makeRouteDestinationForSplit(clusters, destConfig) + } +} + +func (b *Builder) makeGRPCRouteDestination( + computedBackendRefs []*pbmesh.ComputedGRPCBackendRef, + destConfig *pbproxystate.DestinationConfiguration, + targets map[string]*pbmesh.BackendTargetDetails, + defaultDC func(string) string, +) *pbproxystate.RouteDestination { + switch len(computedBackendRefs) { + case 0: + panic("not possible to have a route rule with no backend refs") + case 1: + return b.makeRouteDestinationForDirect(computedBackendRefs[0].BackendTarget, destConfig, targets, defaultDC) + default: + clusters := make([]*pbproxystate.L7WeightedDestinationCluster, 0, len(computedBackendRefs)) + for _, computedBackendRef := range computedBackendRefs { + clusterName := b.backendTargetToClusterName(computedBackendRef.BackendTarget, targets, defaultDC) + + clusters = append(clusters, &pbproxystate.L7WeightedDestinationCluster{ + Name: clusterName, + Weight: &wrapperspb.UInt32Value{ + Value: computedBackendRef.Weight, + }, + }) + } + return b.makeRouteDestinationForSplit(clusters, destConfig) + } +} + +func (b *Builder) makeRouteDestinationForDirect( + backendTarget string, + destConfig *pbproxystate.DestinationConfiguration, + targets map[string]*pbmesh.BackendTargetDetails, + defaultDC func(string) string, +) *pbproxystate.RouteDestination { + clusterName := b.backendTargetToClusterName(backendTarget, targets, defaultDC) + + return &pbproxystate.RouteDestination{ + Destination: &pbproxystate.RouteDestination_Cluster{ + Cluster: &pbproxystate.DestinationCluster{ + Name: clusterName, + }, + }, + DestinationConfiguration: destConfig, + } +} + +func (b *Builder) makeRouteDestinationForSplit( + clusters []*pbproxystate.L7WeightedDestinationCluster, + destConfig *pbproxystate.DestinationConfiguration, +) *pbproxystate.RouteDestination { + return &pbproxystate.RouteDestination{ + Destination: &pbproxystate.RouteDestination_WeightedClusters{ + WeightedClusters: &pbproxystate.L7WeightedClusterGroup{ + Clusters: clusters, + }, + }, + DestinationConfiguration: destConfig, + } +} + +func (b *Builder) makeDestinationConfiguration( + timeouts *pbmesh.HTTPRouteTimeouts, + retries *pbmesh.HTTPRouteRetries, +) *pbproxystate.DestinationConfiguration { + // TODO: prefix rewrite, lb config + + cfg := &pbproxystate.DestinationConfiguration{ + TimeoutConfig: translateTimeouts(timeouts), + RetryPolicy: translateRetries(retries), + } + if cfg.TimeoutConfig == nil && cfg.RetryPolicy == nil { + return nil + } + + return cfg +} + +func makeGRPCRouteMatch(match *pbmesh.GRPCRouteMatch) *pbproxystate.RouteMatch { + panic("TODO") +} + +func makeHTTPRouteMatch(match *pbmesh.HTTPRouteMatch) *pbproxystate.RouteMatch { + em := &pbproxystate.RouteMatch{} + + if match.Path != nil { + // enumcover:pbmesh.PathMatchType + switch match.Path.Type { + case pbmesh.PathMatchType_PATH_MATCH_TYPE_EXACT: + em.PathMatch = &pbproxystate.PathMatch{ + PathMatch: &pbproxystate.PathMatch_Exact{ + Exact: match.Path.Value, + }, + } + case pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX: + em.PathMatch = &pbproxystate.PathMatch{ + PathMatch: &pbproxystate.PathMatch_Prefix{ + Prefix: match.Path.Value, + }, + } + case pbmesh.PathMatchType_PATH_MATCH_TYPE_REGEX: + em.PathMatch = &pbproxystate.PathMatch{ + PathMatch: &pbproxystate.PathMatch_Regex{ + Regex: match.Path.Value, + }, + } + case pbmesh.PathMatchType_PATH_MATCH_TYPE_UNSPECIFIED: + fallthrough // to default + default: + panic(fmt.Sprintf("unknown path match type: %v", match.Path.Type)) + } + } else { + em.PathMatch = &pbproxystate.PathMatch{ + PathMatch: &pbproxystate.PathMatch_Prefix{ + Prefix: "/", + }, + } + } + + if len(match.Headers) > 0 { + em.HeaderMatches = make([]*pbproxystate.HeaderMatch, 0, len(match.Headers)) + for _, hdr := range match.Headers { + eh := &pbproxystate.HeaderMatch{ + Name: hdr.Name, + } + + // enumcover:pbmesh.HeaderMatchType + switch hdr.Type { + case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT: + eh.Match = &pbproxystate.HeaderMatch_Exact{ + Exact: hdr.Value, + } + case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_REGEX: + eh.Match = &pbproxystate.HeaderMatch_Regex{ + Regex: hdr.Value, + } + case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_PREFIX: + eh.Match = &pbproxystate.HeaderMatch_Prefix{ + Prefix: hdr.Value, + } + case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_SUFFIX: + eh.Match = &pbproxystate.HeaderMatch_Suffix{ + Suffix: hdr.Value, + } + case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_PRESENT: + eh.Match = &pbproxystate.HeaderMatch_Present{ + Present: true, + } + case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_UNSPECIFIED: + fallthrough // to default + default: + panic(fmt.Sprintf("unknown header match type: %v", hdr.Type)) + } + + if hdr.Invert { + eh.InvertMatch = true + } + + em.HeaderMatches = append(em.HeaderMatches, eh) + } + } + + if match.Method != "" { + em.MethodMatches = []string{match.Method} + } + + if len(match.QueryParams) > 0 { + em.QueryParameterMatches = make([]*pbproxystate.QueryParameterMatch, 0, len(match.QueryParams)) + for _, qm := range match.QueryParams { + eq := &pbproxystate.QueryParameterMatch{ + Name: qm.Name, + } + + // *QueryParameterMatch_Exact + // enumcover:pbmesh.QueryParamMatchType + switch qm.Type { + case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT: + eq.Match = &pbproxystate.QueryParameterMatch_Exact{ + Exact: qm.Value, + } + case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_REGEX: + eq.Match = &pbproxystate.QueryParameterMatch_Regex{ + Regex: qm.Value, + } + case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_PRESENT: + eq.Match = &pbproxystate.QueryParameterMatch_Present{ + Present: true, + } + case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_UNSPECIFIED: + fallthrough // to default + default: + panic(fmt.Sprintf("unknown query param match type: %v", qm.Type)) + } + + em.QueryParameterMatches = append(em.QueryParameterMatches, eq) + } + } + + return em +} + +func translateTimeouts(timeouts *pbmesh.HTTPRouteTimeouts) *pbproxystate.TimeoutConfig { + if timeouts == nil || (timeouts.Request == nil && timeouts.Idle == nil) { + return nil + } + + return &pbproxystate.TimeoutConfig{ + Timeout: timeouts.Request, + IdleTimeout: timeouts.Idle, + } +} + +func translateRetries(retries *pbmesh.HTTPRouteRetries) *pbproxystate.RetryPolicy { + if retries == nil { + return nil + } + + retryPolicy := &pbproxystate.RetryPolicy{} + if retries.Number != nil { + retryPolicy.NumRetries = retries.Number + } + + // The RetryOn magic values come from: https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/http_filters/router_filter#config-http-filters-router-x-envoy-retry-on + var retryStrings []string + + if len(retries.OnConditions) > 0 { + retryStrings = append(retryStrings, retries.OnConditions...) + } + + if retries.OnConnectFailure { + // connect-failure can be enabled by either adding connect-failure to the RetryOn list or by using the legacy RetryOnConnectFailure option + // Check that it's not already in the RetryOn list, so we don't set it twice + connectFailureExists := false + for _, r := range retryStrings { + if r == "connect-failure" { + connectFailureExists = true + } + } + if !connectFailureExists { + retryStrings = append(retryStrings, "connect-failure") + } + } + + if len(retries.OnStatusCodes) > 0 { + retryStrings = append(retryStrings, "retriable-status-codes") + retryPolicy.RetriableStatusCodes = retries.OnStatusCodes + } + + retryPolicy.RetryOn = strings.Join(retryStrings, ",") + + return retryPolicy +} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/service_port_info.go b/internal/mesh/internal/controllers/sidecarproxy/builder/service_port_info.go deleted file mode 100644 index 82e706467c89..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/service_port_info.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package builder - -import ( - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" -) - -// servicePortInfo is a struct used by the destination builder so that it can pre-process -// what is the service mesh port and what are the distinct ports across the endpoints. -// This pre-processing reduces the iterations during the BuildDestinations processing -// would need to get the ports, check if one was the mesh port, know whether it already -// has a cluster created for it and so on. - -type servicePortInfo struct { - // meshPortName is the name of the port with Mesh Protocol. - meshPortName string - // meshPort is the port with Mesh Protocol. - meshPort *pbcatalog.WorkloadPort - // servicePorts are the distinct ports that need clusters and routers for given destination. - // servicePorts do not include the mesh port and are called servicePorts because they - // belong to the service. - servicePorts map[string]*pbcatalog.WorkloadPort -} - -// newServicePortInfo builds a servicePointInfo given a serviceEndpoints struct. It pre-process -// what the service mesh port and the distinct service ports across the endpoints for a destination. -// The following occurs during pre-processing: -// - a port must be exposed to at least one workload address on every workload in -// the service to be a service port. Otherwise, the system would risk errors. -// - a Workload can optionally define ports specific to workload address. If no -// ports are specified for a workload address, then all the destination ports are -// used. -func newServicePortInfo(serviceEndpoints *pbcatalog.ServiceEndpoints) *servicePortInfo { - spInfo := &servicePortInfo{ - servicePorts: make(map[string]*pbcatalog.WorkloadPort), - } - type seenData struct { - port *pbcatalog.WorkloadPort - seenBy []*int - } - seen := make(map[string]*seenData) - for epIdx, ep := range serviceEndpoints.GetEndpoints() { - for range ep.Addresses { - // iterate through endpoint ports and set the mesh port - // as well as all endpoint ports for this workload if there - // are no specific workload ports. - for epPortName, epPort := range ep.Ports { - // look to set mesh port - if isMeshPort(epPort) { - spInfo.meshPortName = epPortName - spInfo.meshPort = epPort - continue - } - - // otherwise, add all ports for this endpoint. - portData, ok := seen[epPortName] - if ok { - portData.seenBy = append(portData.seenBy, &epIdx) - } else { - seenBy := append([]*int{}, &epIdx) - seen[epPortName] = &seenData{port: epPort, seenBy: seenBy} - } - } - } - } - - for portName, portData := range seen { - // make sure each port is seen by all endpoints - if len(portData.seenBy) == len(serviceEndpoints.GetEndpoints()) { - spInfo.servicePorts[portName] = portData.port - } - } - return spInfo -} - -func isMeshPort(port *pbcatalog.WorkloadPort) bool { - return port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/service_port_info_test.go b/internal/mesh/internal/controllers/sidecarproxy/builder/service_port_info_test.go deleted file mode 100644 index 069be9a444ad..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/service_port_info_test.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package builder - -import ( - "testing" - - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - "github.com/stretchr/testify/require" -) - -// Test_newServicePortInfo test case shows: -// - endpoint 1 has one address with no specific ports. -// - endpoint 2 has one address with no specific ports. -// - the cumulative effect is then the union of endpoints 1 and 2. -func Test_newServicePortInfo(t *testing.T) { - serviceEndpoints := &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "10.0.0.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "admin-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - { - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "10.0.0.2"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - } - expectedResult := &servicePortInfo{ - meshPortName: "mesh", - meshPort: &pbcatalog.WorkloadPort{Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - servicePorts: map[string]*pbcatalog.WorkloadPort{ - "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - }, - } - require.Equal(t, expectedResult, newServicePortInfo(serviceEndpoints)) -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-implicit-and-explicit-destinations-tproxy.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-implicit-and-explicit-destinations-tproxy.golden index afe86fa8cdac..f18e8bcace03 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-implicit-and-explicit-destinations-tproxy.golden +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-implicit-and-explicit-destinations-tproxy.golden @@ -2,6 +2,7 @@ "proxyState": { "clusters": { "tcp.api-1.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", "endpointGroup": { "dynamic": { "config": { @@ -22,9 +23,11 @@ } } } - } + }, + "name": "tcp.api-1.default.dc1.internal.foo.consul" }, "tcp.api-2.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", "endpointGroup": { "dynamic": { "config": { @@ -45,7 +48,8 @@ } } } - } + }, + "name": "tcp.api-2.default.dc1.internal.foo.consul" } }, "identity": { @@ -70,7 +74,9 @@ "routers": [ { "l4": { - "name": "tcp.api-2.default.dc1.internal.foo.consul", + "cluster": { + "name": "tcp.api-2.default.dc1.internal.foo.consul" + }, "statPrefix": "upstream.tcp.api-2.default.default.dc1" }, "match": { @@ -99,7 +105,9 @@ "routers": [ { "l4": { - "name": "tcp.api-1.default.dc1.internal.foo.consul", + "cluster": { + "name": "tcp.api-1.default.dc1.internal.foo.consul" + }, "statPrefix": "upstream.tcp.api-1.default.default.dc1" } } @@ -108,7 +116,7 @@ ] }, "requiredEndpoints": { - "api-1.default.dc1.internal.foo.consul": { + "tcp.api-1.default.dc1.internal.foo.consul": { "id": { "name": "api-1", "tenancy": { @@ -124,7 +132,7 @@ }, "port": "mesh" }, - "api-2.default.dc1.internal.foo.consul": { + "tcp.api-2.default.dc1.internal.foo.consul": { "id": { "name": "api-2", "tenancy": { diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-multi-destination.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-multi-destination.golden index 993e27c619b7..0ed79095ea56 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-multi-destination.golden +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-multi-destination.golden @@ -1,7 +1,18 @@ { "proxyState": { "clusters": { + "null_route_cluster": { + "endpointGroup": { + "static": { + "config": { + "connectTimeout": "10s" + } + } + }, + "name": "null_route_cluster" + }, "tcp.api-1.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", "endpointGroup": { "dynamic": { "config": { @@ -22,9 +33,11 @@ } } } - } + }, + "name": "tcp.api-1.default.dc1.internal.foo.consul" }, "tcp.api-2.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", "endpointGroup": { "dynamic": { "config": { @@ -45,7 +58,8 @@ } } } - } + }, + "name": "tcp.api-2.default.dc1.internal.foo.consul" } }, "identity": { @@ -67,8 +81,23 @@ "routers": [ { "l4": { - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "statPrefix": "upstream.tcp.api-1.default.default.dc1" + "statPrefix": "upstream.tcp.api-1.default.default.dc1", + "weightedClusters": { + "clusters": [ + { + "name": "tcp.api-2.default.dc1.internal.foo.consul", + "weight": 60 + }, + { + "name": "tcp.api-1.default.dc1.internal.foo.consul", + "weight": 40 + }, + { + "name": "null_route_cluster", + "weight": 10 + } + ] + } } } ] @@ -79,7 +108,9 @@ "routers": [ { "l4": { - "name": "tcp.api-2.default.dc1.internal.foo.consul", + "cluster": { + "name": "tcp.api-2.default.dc1.internal.foo.consul" + }, "statPrefix": "upstream.tcp.api-2.default.default.dc1" } } @@ -92,7 +123,7 @@ ] }, "requiredEndpoints": { - "api-1.default.dc1.internal.foo.consul": { + "tcp.api-1.default.dc1.internal.foo.consul": { "id": { "name": "api-1", "tenancy": { @@ -108,7 +139,7 @@ }, "port": "mesh" }, - "api-2.default.dc1.internal.foo.consul": { + "tcp.api-2.default.dc1.internal.foo.consul": { "id": { "name": "api-2", "tenancy": { diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-multiple-implicit-destinations-tproxy.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-multiple-implicit-destinations-tproxy.golden index ed6d05b51662..de512dd1e585 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-multiple-implicit-destinations-tproxy.golden +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-multiple-implicit-destinations-tproxy.golden @@ -2,6 +2,7 @@ "proxyState": { "clusters": { "tcp.api-1.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", "endpointGroup": { "dynamic": { "config": { @@ -22,9 +23,11 @@ } } } - } + }, + "name": "tcp.api-1.default.dc1.internal.foo.consul" }, "tcp.api-2.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", "endpointGroup": { "dynamic": { "config": { @@ -45,7 +48,8 @@ } } } - } + }, + "name": "tcp.api-2.default.dc1.internal.foo.consul" } }, "identity": { @@ -70,7 +74,60 @@ "routers": [ { "l4": { - "name": "tcp.api-1.default.dc1.internal.foo.consul", + "cluster": { + "name": "tcp.api-1.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-1.default.default.dc1" + }, + "match": { + "destinationPort": 8080, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + }, + { + "l4": { + "cluster": { + "name": "tcp.api-2.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-2.default.default.dc1" + }, + "match": { + "destinationPort": 8080, + "prefixRanges": [ + { + "addressPrefix": "2.2.2.2", + "prefixLen": 32 + }, + { + "addressPrefix": "3.3.3.3", + "prefixLen": 32 + } + ] + } + } + ] + }, + { + "capabilities": [ + "CAPABILITY_TRANSPARENT" + ], + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "127.0.0.1", + "port": 15001 + }, + "name": "outbound_listener", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-1.default.dc1.internal.foo.consul" + }, "statPrefix": "upstream.tcp.api-1.default.default.dc1" }, "match": { @@ -85,7 +142,9 @@ }, { "l4": { - "name": "tcp.api-2.default.dc1.internal.foo.consul", + "cluster": { + "name": "tcp.api-2.default.dc1.internal.foo.consul" + }, "statPrefix": "upstream.tcp.api-2.default.default.dc1" }, "match": { @@ -107,7 +166,7 @@ ] }, "requiredEndpoints": { - "api-1.default.dc1.internal.foo.consul": { + "tcp.api-1.default.dc1.internal.foo.consul": { "id": { "name": "api-1", "tenancy": { @@ -123,7 +182,7 @@ }, "port": "mesh" }, - "api-2.default.dc1.internal.foo.consul": { + "tcp.api-2.default.dc1.internal.foo.consul": { "id": { "name": "api-2", "tenancy": { diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-destination-ip-port-bind-address.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-destination-ip-port-bind-address.golden index 5eda0906e5c0..09555899916c 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-destination-ip-port-bind-address.golden +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-destination-ip-port-bind-address.golden @@ -1,7 +1,18 @@ { "proxyState": { "clusters": { + "null_route_cluster": { + "endpointGroup": { + "static": { + "config": { + "connectTimeout": "10s" + } + } + }, + "name": "null_route_cluster" + }, "tcp.api-1.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", "endpointGroup": { "dynamic": { "config": { @@ -22,7 +33,29 @@ } } } - } + }, + "name": "tcp.api-1.default.dc1.internal.foo.consul" + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-2.default.dc1.internal.foo.consul", + "validationContext": {} + } + } + } + }, + "name": "tcp.api-2.default.dc1.internal.foo.consul" } }, "identity": { @@ -44,8 +77,23 @@ "routers": [ { "l4": { - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "statPrefix": "upstream.tcp.api-1.default.default.dc1" + "statPrefix": "upstream.tcp.api-1.default.default.dc1", + "weightedClusters": { + "clusters": [ + { + "name": "tcp.api-2.default.dc1.internal.foo.consul", + "weight": 60 + }, + { + "name": "tcp.api-1.default.dc1.internal.foo.consul", + "weight": 40 + }, + { + "name": "null_route_cluster", + "weight": 10 + } + ] + } } } ] @@ -53,7 +101,7 @@ ] }, "requiredEndpoints": { - "api-1.default.dc1.internal.foo.consul": { + "tcp.api-1.default.dc1.internal.foo.consul": { "id": { "name": "api-1", "tenancy": { @@ -68,6 +116,9 @@ } }, "port": "mesh" + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "port": "mesh" } } } \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-destination-unix-socket-bind-address.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-destination-unix-socket-bind-address.golden index f313ad1cad58..8e1309690224 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-destination-unix-socket-bind-address.golden +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-destination-unix-socket-bind-address.golden @@ -2,6 +2,7 @@ "proxyState": { "clusters": { "tcp.api-2.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", "endpointGroup": { "dynamic": { "config": { @@ -22,7 +23,8 @@ } } } - } + }, + "name": "tcp.api-2.default.dc1.internal.foo.consul" } }, "identity": { @@ -40,7 +42,9 @@ "routers": [ { "l4": { - "name": "tcp.api-2.default.dc1.internal.foo.consul", + "cluster": { + "name": "tcp.api-2.default.dc1.internal.foo.consul" + }, "statPrefix": "upstream.tcp.api-2.default.default.dc1" } } @@ -53,7 +57,7 @@ ] }, "requiredEndpoints": { - "api-2.default.dc1.internal.foo.consul": { + "tcp.api-2.default.dc1.internal.foo.consul": { "id": { "name": "api-2", "tenancy": { diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-implicit-destination-tproxy.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-implicit-destination-tproxy.golden index cc5698fee6ed..549211a135d5 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-implicit-destination-tproxy.golden +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-implicit-destination-tproxy.golden @@ -2,6 +2,7 @@ "proxyState": { "clusters": { "tcp.api-1.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", "endpointGroup": { "dynamic": { "config": { @@ -22,7 +23,8 @@ } } } - } + }, + "name": "tcp.api-1.default.dc1.internal.foo.consul" } }, "identity": { @@ -47,7 +49,9 @@ "routers": [ { "l4": { - "name": "tcp.api-1.default.dc1.internal.foo.consul", + "cluster": { + "name": "tcp.api-1.default.dc1.internal.foo.consul" + }, "statPrefix": "upstream.tcp.api-1.default.default.dc1" }, "match": { @@ -65,7 +69,7 @@ ] }, "requiredEndpoints": { - "api-1.default.dc1.internal.foo.consul": { + "tcp.api-1.default.dc1.internal.foo.consul": { "id": { "name": "api-1", "tenancy": { diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/mixed-multi-destination.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/mixed-multi-destination.golden new file mode 100644 index 000000000000..a273cd4bc335 --- /dev/null +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/mixed-multi-destination.golden @@ -0,0 +1,288 @@ +{ + "proxyState": { + "clusters": { + "http.api-1.default.dc1.internal.foo.consul": { + "altStatName": "http.api-1.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~http" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-1.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" + ] + } + } + } + } + }, + "name": "http.api-1.default.dc1.internal.foo.consul" + }, + "http.api-2.default.dc1.internal.foo.consul": { + "altStatName": "http.api-2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~http" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-2.default.dc1.internal.foo.consul", + "validationContext": {} + } + } + } + }, + "name": "http.api-2.default.dc1.internal.foo.consul" + }, + "null_route_cluster": { + "endpointGroup": { + "static": { + "config": { + "connectTimeout": "10s" + } + } + }, + "name": "null_route_cluster" + }, + "tcp.api-1.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-1.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" + ] + } + } + } + } + }, + "name": "tcp.api-1.default.dc1.internal.foo.consul" + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-2.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" + ] + } + } + } + } + }, + "name": "tcp.api-2.default.dc1.internal.foo.consul" + } + }, + "identity": { + "name": "test-identity", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + } + }, + "listeners": [ + { + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "1.1.1.1", + "port": 1234 + }, + "name": "api-1:tcp:1.1.1.1:1234", + "routers": [ + { + "l4": { + "statPrefix": "upstream.tcp.api-1.default.default.dc1", + "weightedClusters": { + "clusters": [ + { + "name": "tcp.api-2.default.dc1.internal.foo.consul", + "weight": 60 + }, + { + "name": "tcp.api-1.default.dc1.internal.foo.consul", + "weight": 40 + }, + { + "name": "null_route_cluster", + "weight": 10 + } + ] + } + } + } + ] + }, + { + "direction": "DIRECTION_OUTBOUND", + "name": "api-2:tcp:/path/to/socket", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-2.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-2.default.default.dc1" + } + } + ], + "unixSocket": { + "mode": "0666", + "path": "/path/to/socket" + } + }, + { + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "1.1.1.1", + "port": 1234 + }, + "name": "api-1:http:1.1.1.1:1234", + "routers": [ + { + "l7": { + "name": "api-1:http:1.1.1.1:1234", + "statPrefix": "upstream." + } + } + ] + } + ], + "routes": { + "api-1:http:1.1.1.1:1234": { + "virtualHosts": [ + { + "name": "api-1:http:1.1.1.1:1234", + "routeRules": [ + { + "destination": { + "weightedClusters": { + "clusters": [ + { + "name": "http.api-2.default.dc1.internal.foo.consul", + "weight": 60 + }, + { + "name": "http.api-1.default.dc1.internal.foo.consul", + "weight": 40 + }, + { + "name": "null_route_cluster", + "weight": 10 + } + ] + } + }, + "match": { + "pathMatch": { + "prefix": "/" + } + } + }, + { + "destination": { + "cluster": { + "name": "null_route_cluster" + } + }, + "match": { + "pathMatch": { + "prefix": "/" + } + } + } + ] + } + ] + } + } + }, + "requiredEndpoints": { + "http.api-1.default.dc1.internal.foo.consul": { + "id": { + "name": "api-1", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "catalog", + "groupVersion": "v1alpha1", + "kind": "ServiceEndpoints" + } + }, + "port": "mesh" + }, + "http.api-2.default.dc1.internal.foo.consul": { + "port": "mesh" + }, + "tcp.api-1.default.dc1.internal.foo.consul": { + "id": { + "name": "api-1", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "catalog", + "groupVersion": "v1alpha1", + "kind": "ServiceEndpoints" + } + }, + "port": "mesh" + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "id": { + "name": "api-2", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "catalog", + "groupVersion": "v1alpha1", + "kind": "ServiceEndpoints" + } + }, + "port": "mesh" + } + } +} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-multiple-implicit-destinations-tproxy.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-multiple-implicit-destinations-tproxy.golden index 468b47e1763e..d7e81fd8b0b3 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-multiple-implicit-destinations-tproxy.golden +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-multiple-implicit-destinations-tproxy.golden @@ -1,54 +1,236 @@ { "proxyState": { + "clusters": { + "http.api-app.default.dc1.internal.foo.consul": { + "altStatName": "http.api-app.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~http" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" + ] + } + } + } + } + }, + "name": "http.api-app.default.dc1.internal.foo.consul" + }, + "http.api-app2.default.dc1.internal.foo.consul": { + "altStatName": "http.api-app2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~http" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app2.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" + ] + } + } + } + } + }, + "name": "http.api-app2.default.dc1.internal.foo.consul" + }, + "tcp.api-app.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-app.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" + ] + } + } + } + } + }, + "name": "tcp.api-app.default.dc1.internal.foo.consul" + }, + "tcp.api-app2.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-app2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app2.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" + ] + } + } + } + } + }, + "name": "tcp.api-app2.default.dc1.internal.foo.consul" + } + }, "identity": { + "name": "test-identity", "tenancy": { - "partition": "default", "namespace": "default", + "partition": "default", "peerName": "local" - }, - "name": "test-identity" + } }, "listeners": [ { - "name": "outbound_listener", + "capabilities": [ + "CAPABILITY_TRANSPARENT" + ], "direction": "DIRECTION_OUTBOUND", "hostPort": { "host": "127.0.0.1", "port": 15001 }, + "name": "outbound_listener", "routers": [ { + "l4": { + "cluster": { + "name": "tcp.api-app.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-app.default.default.dc1" + }, "match": { + "destinationPort": 8080, "prefixRanges": [ { "addressPrefix": "1.1.1.1", "prefixLen": 32 } - ], - "destinationPort": 8080 - }, + ] + } + }, + { "l4": { - "name": "admin-port.api-app.default.dc1.internal.foo.consul", - "statPrefix": "upstream.admin-port.api-app.default.default.dc1" + "cluster": { + "name": "tcp.api-app2.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-app2.default.default.dc1" + }, + "match": { + "destinationPort": 8080, + "prefixRanges": [ + { + "addressPrefix": "2.2.2.2", + "prefixLen": 32 + }, + { + "addressPrefix": "3.3.3.3", + "prefixLen": 32 + } + ] } }, { + "l7": { + "name": "outbound_listener", + "statPrefix": "upstream." + }, "match": { "prefixRanges": [ { "addressPrefix": "1.1.1.1", "prefixLen": 32 } - ], - "destinationPort": 9090 + ] + } + }, + { + "l7": { + "name": "outbound_listener", + "statPrefix": "upstream." }, + "match": { + "prefixRanges": [ + { + "addressPrefix": "2.2.2.2", + "prefixLen": 32 + }, + { + "addressPrefix": "3.3.3.3", + "prefixLen": 32 + } + ] + } + } + ] + }, + { + "capabilities": [ + "CAPABILITY_TRANSPARENT" + ], + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "127.0.0.1", + "port": 15001 + }, + "name": "outbound_listener", + "routers": [ + { "l4": { - "name": "api-port.api-app.default.dc1.internal.foo.consul", - "statPrefix": "upstream.api-port.api-app.default.default.dc1" + "cluster": { + "name": "tcp.api-app.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-app.default.default.dc1" + }, + "match": { + "destinationPort": 8080, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] } }, { + "l4": { + "cluster": { + "name": "tcp.api-app2.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-app2.default.default.dc1" + }, "match": { + "destinationPort": 8080, "prefixRanges": [ { "addressPrefix": "2.2.2.2", @@ -58,15 +240,28 @@ "addressPrefix": "3.3.3.3", "prefixLen": 32 } - ], - "destinationPort": 8080 + ] + } + }, + { + "l7": { + "name": "outbound_listener", + "statPrefix": "upstream." }, - "l4": { - "name": "admin-port.api-app2.default.dc1.internal.foo.consul", - "statPrefix": "upstream.admin-port.api-app2.default.default.dc1" + "match": { + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] } }, { + "l7": { + "name": "outbound_listener", + "statPrefix": "upstream." + }, "match": { "prefixRanges": [ { @@ -77,122 +272,209 @@ "addressPrefix": "3.3.3.3", "prefixLen": 32 } - ], - "destinationPort": 9090 - }, - "l4": { - "name": "api-port.api-app2.default.dc1.internal.foo.consul", - "statPrefix": "upstream.api-port.api-app2.default.default.dc1" + ] } } - ], + ] + }, + { "capabilities": [ "CAPABILITY_TRANSPARENT" - ] - } - ], - "clusters": { - "admin-port.api-app.default.dc1.internal.foo.consul": { - "endpointGroup": { - "dynamic": { - "config": { - "disablePanicThreshold": true + ], + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "127.0.0.1", + "port": 15001 + }, + "name": "outbound_listener", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-app.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-app.default.default.dc1" }, - "outboundTls": { - "outboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ] - }, - "sni": "api-app.default.dc1.internal.foo.consul" + "match": { + "destinationPort": 8080, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + }, + { + "l4": { + "cluster": { + "name": "tcp.api-app2.default.dc1.internal.foo.consul" }, - "alpnProtocols": [ - "consul~admin-port" + "statPrefix": "upstream.tcp.api-app2.default.default.dc1" + }, + "match": { + "destinationPort": 8080, + "prefixRanges": [ + { + "addressPrefix": "2.2.2.2", + "prefixLen": 32 + }, + { + "addressPrefix": "3.3.3.3", + "prefixLen": 32 + } ] } - } - } - }, - "api-port.api-app.default.dc1.internal.foo.consul": { - "endpointGroup": { - "dynamic": { - "config": { - "disablePanicThreshold": true + }, + { + "l7": { + "name": "outbound_listener", + "statPrefix": "upstream." }, - "outboundTls": { - "outboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ] + "match": { + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + }, + { + "l7": { + "name": "outbound_listener", + "statPrefix": "upstream." + }, + "match": { + "prefixRanges": [ + { + "addressPrefix": "2.2.2.2", + "prefixLen": 32 }, - "sni": "api-app.default.dc1.internal.foo.consul" - }, - "alpnProtocols": [ - "consul~api-port" + { + "addressPrefix": "3.3.3.3", + "prefixLen": 32 + } ] } } - } + ] }, - "admin-port.api-app2.default.dc1.internal.foo.consul": { - "endpointGroup": { - "dynamic": { - "config": { - "disablePanicThreshold": true + { + "capabilities": [ + "CAPABILITY_TRANSPARENT" + ], + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "127.0.0.1", + "port": 15001 + }, + "name": "outbound_listener", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-app.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-app.default.default.dc1" }, - "outboundTls": { - "outboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" - ] - }, - "sni": "api-app2.default.dc1.internal.foo.consul" + "match": { + "destinationPort": 8080, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + }, + { + "l4": { + "cluster": { + "name": "tcp.api-app2.default.dc1.internal.foo.consul" }, - "alpnProtocols": [ - "consul~admin-port" + "statPrefix": "upstream.tcp.api-app2.default.default.dc1" + }, + "match": { + "destinationPort": 8080, + "prefixRanges": [ + { + "addressPrefix": "2.2.2.2", + "prefixLen": 32 + }, + { + "addressPrefix": "3.3.3.3", + "prefixLen": 32 + } ] } - } - } - }, - "api-port.api-app2.default.dc1.internal.foo.consul": { - "endpointGroup": { - "dynamic": { - "config": { - "disablePanicThreshold": true + }, + { + "l7": { + "name": "outbound_listener", + "statPrefix": "upstream." }, - "outboundTls": { - "outboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" - ] + "match": { + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + }, + { + "l7": { + "name": "outbound_listener", + "statPrefix": "upstream." + }, + "match": { + "prefixRanges": [ + { + "addressPrefix": "2.2.2.2", + "prefixLen": 32 }, - "sni": "api-app2.default.dc1.internal.foo.consul" - }, - "alpnProtocols": [ - "consul~api-port" + { + "addressPrefix": "3.3.3.3", + "prefixLen": 32 + } ] } } - } + ] + } + ], + "routes": { + "outbound_listener": { + "virtualHosts": [ + { + "name": "outbound_listener", + "routeRules": [ + { + "destination": { + "cluster": { + "name": "http.api-app2.default.dc1.internal.foo.consul" + } + }, + "match": { + "pathMatch": { + "prefix": "/" + } + } + } + ] + } + ] } } }, "requiredEndpoints": { - "api-app.default.dc1.internal.foo.consul": { + "http.api-app.default.dc1.internal.foo.consul": { "id": { "name": "api-app", "tenancy": { - "partition": "default", "namespace": "default", + "partition": "default", "peerName": "local" }, "type": { @@ -203,12 +485,44 @@ }, "port": "mesh" }, - "api-app2.default.dc1.internal.foo.consul": { + "http.api-app2.default.dc1.internal.foo.consul": { "id": { "name": "api-app2", "tenancy": { + "namespace": "default", "partition": "default", + "peerName": "local" + }, + "type": { + "group": "catalog", + "groupVersion": "v1alpha1", + "kind": "ServiceEndpoints" + } + }, + "port": "mesh" + }, + "tcp.api-app.default.dc1.internal.foo.consul": { + "id": { + "name": "api-app", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "catalog", + "groupVersion": "v1alpha1", + "kind": "ServiceEndpoints" + } + }, + "port": "mesh" + }, + "tcp.api-app2.default.dc1.internal.foo.consul": { + "id": { + "name": "api-app2", + "tenancy": { "namespace": "default", + "partition": "default", "peerName": "local" }, "type": { diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-single-implicit-destination-tproxy.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-single-implicit-destination-tproxy.golden index ce239c7ed357..10a41c437007 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-single-implicit-destination-tproxy.golden +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-single-implicit-destination-tproxy.golden @@ -1,114 +1,202 @@ { "proxyState": { + "clusters": { + "http.api-app.default.dc1.internal.foo.consul": { + "altStatName": "http.api-app.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~http" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" + ] + } + } + } + } + }, + "name": "http.api-app.default.dc1.internal.foo.consul" + }, + "tcp.api-app.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-app.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" + ] + } + } + } + } + }, + "name": "tcp.api-app.default.dc1.internal.foo.consul" + } + }, "identity": { + "name": "test-identity", "tenancy": { - "partition": "default", "namespace": "default", + "partition": "default", "peerName": "local" - }, - "name": "test-identity" + } }, "listeners": [ { - "name": "outbound_listener", + "capabilities": [ + "CAPABILITY_TRANSPARENT" + ], "direction": "DIRECTION_OUTBOUND", "hostPort": { "host": "127.0.0.1", "port": 15001 }, + "name": "outbound_listener", "routers": [ { + "l4": { + "cluster": { + "name": "tcp.api-app.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-app.default.default.dc1" + }, "match": { + "destinationPort": 8080, "prefixRanges": [ { "addressPrefix": "1.1.1.1", "prefixLen": 32 } - ], - "destinationPort": 8080 - }, - "l4": { - "name": "admin-port.api-app.default.dc1.internal.foo.consul", - "statPrefix": "upstream.admin-port.api-app.default.default.dc1" + ] } }, { + "l7": { + "name": "outbound_listener", + "statPrefix": "upstream." + }, "match": { "prefixRanges": [ { "addressPrefix": "1.1.1.1", "prefixLen": 32 } - ], - "destinationPort": 9090 - }, - "l4": { - "name": "api-port.api-app.default.dc1.internal.foo.consul", - "statPrefix": "upstream.api-port.api-app.default.default.dc1" + ] } } - ], + ] + }, + { "capabilities": [ "CAPABILITY_TRANSPARENT" - ] - } - ], - "clusters": { - "api-port.api-app.default.dc1.internal.foo.consul": { - "endpointGroup": { - "dynamic": { - "config": { - "disablePanicThreshold": true - }, - "outboundTls": { - "outboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ] - }, - "sni": "api-app.default.dc1.internal.foo.consul" + ], + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "127.0.0.1", + "port": 15001 + }, + "name": "outbound_listener", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-app.default.dc1.internal.foo.consul" }, - "alpnProtocols": [ - "consul~api-port" + "statPrefix": "upstream.tcp.api-app.default.default.dc1" + }, + "match": { + "destinationPort": 8080, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } ] } - } - } - }, - "admin-port.api-app.default.dc1.internal.foo.consul": { - "endpointGroup": { - "dynamic": { - "config": { - "disablePanicThreshold": true + }, + { + "l7": { + "name": "outbound_listener", + "statPrefix": "upstream." }, - "outboundTls": { - "outboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ] - }, - "sni": "api-app.default.dc1.internal.foo.consul" - }, - "alpnProtocols": [ - "consul~admin-port" + "match": { + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } ] } } - } + ] + } + ], + "routes": { + "outbound_listener": { + "virtualHosts": [ + { + "name": "outbound_listener", + "routeRules": [ + { + "destination": { + "cluster": { + "name": "http.api-app.default.dc1.internal.foo.consul" + } + }, + "match": { + "pathMatch": { + "prefix": "/" + } + } + } + ] + } + ] } } }, "requiredEndpoints": { - "api-app.default.dc1.internal.foo.consul": { + "http.api-app.default.dc1.internal.foo.consul": { "id": { "name": "api-app", "tenancy": { + "namespace": "default", "partition": "default", + "peerName": "local" + }, + "type": { + "group": "catalog", + "groupVersion": "v1alpha1", + "kind": "ServiceEndpoints" + } + }, + "port": "mesh" + }, + "tcp.api-app.default.dc1.internal.foo.consul": { + "id": { + "name": "api-app", + "tenancy": { "namespace": "default", + "partition": "default", "peerName": "local" }, "type": { diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-single-implicit-destination-with-multiple-workloads-tproxy.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-single-implicit-destination-with-multiple-workloads-tproxy.golden index 1161b5c97315..10a41c437007 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-single-implicit-destination-with-multiple-workloads-tproxy.golden +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-single-implicit-destination-with-multiple-workloads-tproxy.golden @@ -1,117 +1,202 @@ { - "requiredLeafCertificates": {}, - "requiredTrustBundles": {}, "proxyState": { + "clusters": { + "http.api-app.default.dc1.internal.foo.consul": { + "altStatName": "http.api-app.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~http" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" + ] + } + } + } + } + }, + "name": "http.api-app.default.dc1.internal.foo.consul" + }, + "tcp.api-app.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-app.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" + ] + } + } + } + } + }, + "name": "tcp.api-app.default.dc1.internal.foo.consul" + } + }, "identity": { + "name": "test-identity", "tenancy": { - "partition": "default", "namespace": "default", + "partition": "default", "peerName": "local" - }, - "name": "test-identity" + } }, "listeners": [ { - "name": "outbound_listener", + "capabilities": [ + "CAPABILITY_TRANSPARENT" + ], "direction": "DIRECTION_OUTBOUND", "hostPort": { "host": "127.0.0.1", "port": 15001 }, + "name": "outbound_listener", "routers": [ { + "l4": { + "cluster": { + "name": "tcp.api-app.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-app.default.default.dc1" + }, "match": { + "destinationPort": 8080, "prefixRanges": [ { "addressPrefix": "1.1.1.1", "prefixLen": 32 } - ], - "destinationPort": 8080 - }, - "l4": { - "name": "admin-port.api-app.default.dc1.internal.foo.consul", - "statPrefix": "upstream.admin-port.api-app.default.default.dc1" + ] } }, { + "l7": { + "name": "outbound_listener", + "statPrefix": "upstream." + }, "match": { "prefixRanges": [ { "addressPrefix": "1.1.1.1", "prefixLen": 32 } - ], - "destinationPort": 9090 - }, - "l4": { - "name": "api-port.api-app.default.dc1.internal.foo.consul", - "statPrefix": "upstream.api-port.api-app.default.default.dc1" + ] } } - ], + ] + }, + { "capabilities": [ "CAPABILITY_TRANSPARENT" - ] - } - ], - "clusters": { - "api-port.api-app.default.dc1.internal.foo.consul": { - "endpointGroup": { - "dynamic": { - "config": { - "disablePanicThreshold": true - }, - "outboundTls": { - "outboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ] - }, - "sni": "api-app.default.dc1.internal.foo.consul" + ], + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "127.0.0.1", + "port": 15001 + }, + "name": "outbound_listener", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-app.default.dc1.internal.foo.consul" }, - "alpnProtocols": [ - "consul~api-port" + "statPrefix": "upstream.tcp.api-app.default.default.dc1" + }, + "match": { + "destinationPort": 8080, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } ] } - } - } - }, - "admin-port.api-app.default.dc1.internal.foo.consul": { - "endpointGroup": { - "dynamic": { - "config": { - "disablePanicThreshold": true + }, + { + "l7": { + "name": "outbound_listener", + "statPrefix": "upstream." }, - "outboundTls": { - "outboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ] - }, - "sni": "api-app.default.dc1.internal.foo.consul" - }, - "alpnProtocols": [ - "consul~admin-port" + "match": { + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } ] } } - } + ] } - }, - "endpoints": {} + ], + "routes": { + "outbound_listener": { + "virtualHosts": [ + { + "name": "outbound_listener", + "routeRules": [ + { + "destination": { + "cluster": { + "name": "http.api-app.default.dc1.internal.foo.consul" + } + }, + "match": { + "pathMatch": { + "prefix": "/" + } + } + } + ] + } + ] + } + } }, "requiredEndpoints": { - "api-app.default.dc1.internal.foo.consul": { + "http.api-app.default.dc1.internal.foo.consul": { "id": { "name": "api-app", "tenancy": { + "namespace": "default", "partition": "default", + "peerName": "local" + }, + "type": { + "group": "catalog", + "groupVersion": "v1alpha1", + "kind": "ServiceEndpoints" + } + }, + "port": "mesh" + }, + "tcp.api-app.default.dc1.internal.foo.consul": { + "id": { + "name": "api-app", + "tenancy": { "namespace": "default", + "partition": "default", "peerName": "local" }, "type": { diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/l4-multiple-workload-addresses-with-specific-ports.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/l4-multiple-workload-addresses-with-specific-ports.golden index 48285321bd90..9d331630a5ea 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/l4-multiple-workload-addresses-with-specific-ports.golden +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/l4-multiple-workload-addresses-with-specific-ports.golden @@ -48,7 +48,9 @@ } }, "l4": { - "name": "local_app:port1", + "cluster": { + "name": "local_app:port1" + }, "statPrefix": "public_listener" }, "match": { diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/l4-multiple-workload-addresses-without-ports.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/l4-multiple-workload-addresses-without-ports.golden index 80eb8a8b05b5..6269f9b3b9c2 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/l4-multiple-workload-addresses-without-ports.golden +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/l4-multiple-workload-addresses-without-ports.golden @@ -48,7 +48,9 @@ } }, "l4": { - "name": "local_app:port1", + "cluster": { + "name": "local_app:port1" + }, "statPrefix": "public_listener" }, "match": { diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/l4-single-workload-address-without-ports.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/l4-single-workload-address-without-ports.golden index 80eb8a8b05b5..6269f9b3b9c2 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/l4-single-workload-address-without-ports.golden +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/l4-single-workload-address-without-ports.golden @@ -48,7 +48,9 @@ } }, "l4": { - "name": "local_app:port1", + "cluster": { + "name": "local_app:port1" + }, "statPrefix": "public_listener" }, "match": { diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden index 0a08401fb97d..cd5e8c12522b 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden @@ -1,32 +1,57 @@ { "proxyState": { + "clusters": { + "local_app:admin-port": { + "endpointGroup": { + "static": {} + } + }, + "local_app:api-port": { + "endpointGroup": { + "static": {} + } + } + }, + "endpoints": { + "local_app:admin-port": { + "endpoints": [ + { + "hostPort": { + "host": "127.0.0.1", + "port": 8080 + } + } + ] + }, + "local_app:api-port": { + "endpoints": [ + { + "hostPort": { + "host": "127.0.0.1", + "port": 9090 + } + } + ] + } + }, "identity": { + "name": "test-identity", "tenancy": { - "partition": "default", "namespace": "default", + "partition": "default", "peerName": "local" - }, - "name": "test-identity" + } }, "listeners": [ { - "name": "public_listener", "direction": "DIRECTION_INBOUND", "hostPort": { "host": "10.0.0.3", "port": 20000 }, + "name": "public_listener", "routers": [ { - "match": { - "alpnProtocols": [ - "consul~admin-port" - ] - }, - "l4": { - "name": "local_app:admin-port", - "statPrefix": "public_listener" - }, "inboundTls": { "inboundMesh": { "identityKey": "test-identity", @@ -36,18 +61,20 @@ ] } } - } - }, - { - "match": { - "alpnProtocols": [ - "consul~api-port" - ] }, "l4": { - "name": "local_app:api-port", + "cluster": { + "name": "local_app:admin-port" + }, "statPrefix": "public_listener" }, + "match": { + "alpnProtocols": [ + "consul~admin-port" + ] + } + }, + { "inboundTls": { "inboundMesh": { "identityKey": "test-identity", @@ -57,45 +84,22 @@ ] } } + }, + "l4": { + "cluster": { + "name": "local_app:api-port" + }, + "statPrefix": "public_listener" + }, + "match": { + "alpnProtocols": [ + "consul~api-port" + ] } } ] } - ], - "clusters": { - "local_app:api-port": { - "endpointGroup": { - "static": {} - } - }, - "local_app:admin-port": { - "endpointGroup": { - "static": {} - } - } - }, - "endpoints": { - "local_app:admin-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:api-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - } - } + ] }, "requiredLeafCertificates": { "test-identity": { @@ -108,6 +112,5 @@ "local": { "peer": "local" } - }, - "requiredEndpoints": {} + } } \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-multiple-workload-addresses-without-ports.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-multiple-workload-addresses-without-ports.golden index 662eefb21c43..170f72cb3562 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-multiple-workload-addresses-without-ports.golden +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-multiple-workload-addresses-without-ports.golden @@ -1,32 +1,57 @@ { "proxyState": { + "clusters": { + "local_app:admin-port": { + "endpointGroup": { + "static": {} + } + }, + "local_app:api-port": { + "endpointGroup": { + "static": {} + } + } + }, + "endpoints": { + "local_app:admin-port": { + "endpoints": [ + { + "hostPort": { + "host": "127.0.0.1", + "port": 8080 + } + } + ] + }, + "local_app:api-port": { + "endpoints": [ + { + "hostPort": { + "host": "127.0.0.1", + "port": 9090 + } + } + ] + } + }, "identity": { + "name": "test-identity", "tenancy": { - "partition": "default", "namespace": "default", + "partition": "default", "peerName": "local" - }, - "name": "test-identity" + } }, "listeners": [ { - "name": "public_listener", "direction": "DIRECTION_INBOUND", "hostPort": { "host": "10.0.0.1", "port": 20000 }, + "name": "public_listener", "routers": [ { - "match": { - "alpnProtocols": [ - "consul~admin-port" - ] - }, - "l4": { - "name": "local_app:admin-port", - "statPrefix": "public_listener" - }, "inboundTls": { "inboundMesh": { "identityKey": "test-identity", @@ -36,18 +61,20 @@ ] } } - } - }, - { - "match": { - "alpnProtocols": [ - "consul~api-port" - ] }, "l4": { - "name": "local_app:api-port", + "cluster": { + "name": "local_app:admin-port" + }, "statPrefix": "public_listener" }, + "match": { + "alpnProtocols": [ + "consul~admin-port" + ] + } + }, + { "inboundTls": { "inboundMesh": { "identityKey": "test-identity", @@ -57,45 +84,22 @@ ] } } + }, + "l4": { + "cluster": { + "name": "local_app:api-port" + }, + "statPrefix": "public_listener" + }, + "match": { + "alpnProtocols": [ + "consul~api-port" + ] } } ] } - ], - "clusters": { - "local_app:api-port": { - "endpointGroup": { - "static": {} - } - }, - "local_app:admin-port": { - "endpointGroup": { - "static": {} - } - } - }, - "endpoints": { - "local_app:admin-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:api-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - } - } + ] }, "requiredLeafCertificates": { "test-identity": { @@ -108,6 +112,5 @@ "local": { "peer": "local" } - }, - "requiredEndpoints": {} + } } \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-single-workload-address-without-ports.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-single-workload-address-without-ports.golden index 662eefb21c43..170f72cb3562 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-single-workload-address-without-ports.golden +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-single-workload-address-without-ports.golden @@ -1,32 +1,57 @@ { "proxyState": { + "clusters": { + "local_app:admin-port": { + "endpointGroup": { + "static": {} + } + }, + "local_app:api-port": { + "endpointGroup": { + "static": {} + } + } + }, + "endpoints": { + "local_app:admin-port": { + "endpoints": [ + { + "hostPort": { + "host": "127.0.0.1", + "port": 8080 + } + } + ] + }, + "local_app:api-port": { + "endpoints": [ + { + "hostPort": { + "host": "127.0.0.1", + "port": 9090 + } + } + ] + } + }, "identity": { + "name": "test-identity", "tenancy": { - "partition": "default", "namespace": "default", + "partition": "default", "peerName": "local" - }, - "name": "test-identity" + } }, "listeners": [ { - "name": "public_listener", "direction": "DIRECTION_INBOUND", "hostPort": { "host": "10.0.0.1", "port": 20000 }, + "name": "public_listener", "routers": [ { - "match": { - "alpnProtocols": [ - "consul~admin-port" - ] - }, - "l4": { - "name": "local_app:admin-port", - "statPrefix": "public_listener" - }, "inboundTls": { "inboundMesh": { "identityKey": "test-identity", @@ -36,18 +61,20 @@ ] } } - } - }, - { - "match": { - "alpnProtocols": [ - "consul~api-port" - ] }, "l4": { - "name": "local_app:api-port", + "cluster": { + "name": "local_app:admin-port" + }, "statPrefix": "public_listener" }, + "match": { + "alpnProtocols": [ + "consul~admin-port" + ] + } + }, + { "inboundTls": { "inboundMesh": { "identityKey": "test-identity", @@ -57,45 +84,22 @@ ] } } + }, + "l4": { + "cluster": { + "name": "local_app:api-port" + }, + "statPrefix": "public_listener" + }, + "match": { + "alpnProtocols": [ + "consul~api-port" + ] } } ] } - ], - "clusters": { - "local_app:api-port": { - "endpointGroup": { - "static": {} - } - }, - "local_app:admin-port": { - "endpointGroup": { - "static": {} - } - } - }, - "endpoints": { - "local_app:admin-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:api-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - } - } + ] }, "requiredLeafCertificates": { "test-identity": { @@ -108,6 +112,5 @@ "local": { "peer": "local" } - }, - "requiredEndpoints": {} + } } \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/controller.go b/internal/mesh/internal/controllers/sidecarproxy/controller.go index bb8ddc3c7b78..2e3649cbcf89 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/controller.go +++ b/internal/mesh/internal/controllers/sidecarproxy/controller.go @@ -16,7 +16,6 @@ import ( "github.com/hashicorp/consul/internal/mesh/internal/controllers/sidecarproxy/fetcher" "github.com/hashicorp/consul/internal/mesh/internal/mappers/sidecarproxymapper" "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/mesh/internal/types/intermediate" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/proto-public/pbresource" ) @@ -26,33 +25,84 @@ const ControllerName = "consul.io/sidecar-proxy-controller" type TrustDomainFetcher func() (string, error) -func Controller(destinationsCache *sidecarproxycache.DestinationsCache, +func Controller( + destinationsCache *sidecarproxycache.DestinationsCache, proxyCfgCache *sidecarproxycache.ProxyConfigurationCache, + computedRoutesCache *sidecarproxycache.ComputedRoutesCache, mapper *sidecarproxymapper.Mapper, trustDomainFetcher TrustDomainFetcher, - dc string) controller.Controller { - - if destinationsCache == nil || proxyCfgCache == nil || mapper == nil || trustDomainFetcher == nil { - panic("destinations cache, proxy configuration cache, mapper and trust domain fetcher are required") + dc string, +) controller.Controller { + if destinationsCache == nil || proxyCfgCache == nil || computedRoutesCache == nil || mapper == nil || trustDomainFetcher == nil { + panic("destinations cache, proxy configuration cache, computed routes cache, mapper, and trust domain fetcher are required") } + /* + Workload PST + Upstreams PST(==Workload) + ComputedRoutes Service(upstream) + ComputedRoutes Service(disco) + ServiceEndpoints Service(disco) + + These relationships then dicate the following reconcile logic. + + controller: read workload for PST + controller: read previous PST + controller: read ProxyConfiguration for Workload + controller: use cached Upstreams data to walk explicit upstreams + + fetcher: read Upstreams to find single Upstream + fetcher: read Service(upstream) + fetcher: read ComputedRoutes + + fetcher: read ServiceEndpoints + + + + fetcher: list ALL ComputedRoutes + + fetcher: read Service(upstream) + + fetcher: read ServiceEndpoints + + + + */ + + /* + Which means for equivalence, the following mapper relationships should exist: + + Service: find upstreams with Service; Recurse(Upstreams) + ServiceEndpoints: ServiceEndpoints=>Service; find ComputedRoutes with this in a Target or FailoverConfig; Recurse(ComputedRoutes) + Upstreams: use selector to select workloads; workloads=>PST + ProxyConfiguration: use selector to select workloads; workloads=>PST + ComputedRoutes: CR=>Service; find upstreams with Service; Recurse(Upstreams) + [implicit/temp]: trigger all + */ + return controller.ForType(types.ProxyStateTemplateType). + WithWatch(catalog.ServiceType, mapper.MapServiceToProxyStateTemplate). WithWatch(catalog.ServiceEndpointsType, mapper.MapServiceEndpointsToProxyStateTemplate). WithWatch(types.UpstreamsType, mapper.MapDestinationsToProxyStateTemplate). WithWatch(types.ProxyConfigurationType, mapper.MapProxyConfigurationToProxyStateTemplate). + WithWatch(types.ComputedRoutesType, mapper.MapComputedRoutesToProxyStateTemplate). WithReconciler(&reconciler{ - destinationsCache: destinationsCache, - proxyCfgCache: proxyCfgCache, - getTrustDomain: trustDomainFetcher, - dc: dc, + destinationsCache: destinationsCache, + proxyCfgCache: proxyCfgCache, + computedRoutesCache: computedRoutesCache, + getTrustDomain: trustDomainFetcher, + dc: dc, }) } type reconciler struct { - destinationsCache *sidecarproxycache.DestinationsCache - proxyCfgCache *sidecarproxycache.ProxyConfigurationCache - getTrustDomain TrustDomainFetcher - dc string + destinationsCache *sidecarproxycache.DestinationsCache + proxyCfgCache *sidecarproxycache.ProxyConfigurationCache + computedRoutesCache *sidecarproxycache.ComputedRoutesCache + getTrustDomain TrustDomainFetcher + dc string } func (r *reconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { @@ -61,7 +111,12 @@ func (r *reconciler) Reconcile(ctx context.Context, rt controller.Runtime, req c rt.Logger.Trace("reconciling proxy state template") // Instantiate a data fetcher to fetch all reconciliation data. - dataFetcher := fetcher.New(rt.Client, r.destinationsCache, r.proxyCfgCache) + dataFetcher := fetcher.New( + rt.Client, + r.destinationsCache, + r.proxyCfgCache, + r.computedRoutesCache, + ) // Check if the workload exists. workloadID := resource.ReplaceType(catalog.WorkloadType, req.ID) @@ -88,7 +143,7 @@ func (r *reconciler) Reconcile(ctx context.Context, rt controller.Runtime, req c rt.Logger.Trace("proxy state template for this workload doesn't yet exist; generating a new one") } - if !workload.Workload.IsMeshEnabled() { + if !fetcher.IsWorkloadMeshEnabled(workload.Data.Ports) { // Skip non-mesh workloads. // If there's existing proxy state template, delete it. @@ -121,7 +176,7 @@ func (r *reconciler) Reconcile(ctx context.Context, rt controller.Runtime, req c return err } b := builder.New(req.ID, identityRefFromWorkload(workload), trustDomain, r.dc, proxyCfg). - BuildLocalApp(workload.Workload) + BuildLocalApp(workload.Data) // Get all destinationsData. destinationsRefs := r.destinationsCache.DestinationsBySourceProxy(req.ID) @@ -143,7 +198,7 @@ func (r *reconciler) Reconcile(ctx context.Context, rt controller.Runtime, req c newProxyTemplate := b.Build() - if proxyStateTemplate == nil || !proto.Equal(proxyStateTemplate.Tmpl, newProxyTemplate) { + if proxyStateTemplate == nil || !proto.Equal(proxyStateTemplate.Data, newProxyTemplate) { if proxyStateTemplate == nil { req.ID.Uid = "" } @@ -191,9 +246,9 @@ func (r *reconciler) Reconcile(ctx context.Context, rt controller.Runtime, req c return nil } -func identityRefFromWorkload(w *intermediate.Workload) *pbresource.Reference { +func identityRefFromWorkload(w *types.DecodedWorkload) *pbresource.Reference { return &pbresource.Reference{ - Name: w.Workload.Identity, + Name: w.Data.Identity, Tenancy: w.Resource.Id.Tenancy, } } diff --git a/internal/mesh/internal/controllers/sidecarproxy/controller_test.go b/internal/mesh/internal/controllers/sidecarproxy/controller_test.go index e06f058d2b8e..d972fd8d79f3 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/controller_test.go +++ b/internal/mesh/internal/controllers/sidecarproxy/controller_test.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/consul/internal/catalog" "github.com/hashicorp/consul/internal/controller" "github.com/hashicorp/consul/internal/mesh/internal/cache/sidecarproxycache" + "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/routestest" "github.com/hashicorp/consul/internal/mesh/internal/controllers/sidecarproxy/builder" "github.com/hashicorp/consul/internal/mesh/internal/controllers/sidecarproxy/status" "github.com/hashicorp/consul/internal/mesh/internal/mappers/sidecarproxymapper" @@ -40,12 +41,20 @@ type meshControllerTestSuite struct { ctl *reconciler ctx context.Context - apiWorkloadID *pbresource.ID - apiWorkload *pbcatalog.Workload - apiService *pbresource.Resource - apiEndpoints *pbresource.Resource - apiEndpointsData *pbcatalog.ServiceEndpoints - webWorkload *pbresource.Resource + apiWorkloadID *pbresource.ID + apiWorkload *pbcatalog.Workload + apiService *pbresource.Resource + apiServiceData *pbcatalog.Service + apiEndpoints *pbresource.Resource + apiEndpointsData *pbcatalog.ServiceEndpoints + webWorkload *pbresource.Resource + + dbWorkloadID *pbresource.ID + dbWorkload *pbcatalog.Workload + dbService *pbresource.Resource + dbEndpoints *pbresource.Resource + dbEndpointsData *pbcatalog.ServiceEndpoints + proxyStateTemplate *pbmesh.ProxyStateTemplate } @@ -63,6 +72,50 @@ func (suite *meshControllerTestSuite) SetupTest() { }, } + { + // DB will be a service with a single workload, IN the mesh that will + // be a destination of web. + + suite.dbWorkload = &pbcatalog.Workload{ + Identity: "db-identity", + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "10.0.4.1"}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + } + suite.dbWorkloadID = resourcetest.Resource(catalog.WorkloadType, "db-abc"). + WithData(suite.T(), suite.dbWorkload). + Write(suite.T(), resourceClient).Id + + suite.dbService = resourcetest.Resource(catalog.ServiceType, "db-service"). + WithData(suite.T(), &pbcatalog.Service{ + Workloads: &pbcatalog.WorkloadSelector{Names: []string{"db-abc"}}, + VirtualIps: []string{"1.1.1.1"}, + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }}). + Write(suite.T(), suite.client) + + suite.dbEndpointsData = &pbcatalog.ServiceEndpoints{ + Endpoints: []*pbcatalog.Endpoint{ + { + TargetRef: suite.dbWorkloadID, + Addresses: suite.dbWorkload.Addresses, + Ports: suite.dbWorkload.Ports, + Identity: "db-identity", + }, + }, + } + suite.dbEndpoints = resourcetest.Resource(catalog.ServiceEndpointsType, "db-service"). + WithData(suite.T(), suite.dbEndpointsData). + Write(suite.T(), suite.client) + + } + suite.apiWorkload = &pbcatalog.Workload{ Identity: "api-identity", Addresses: []*pbcatalog.WorkloadAddress{ @@ -80,13 +133,17 @@ func (suite *meshControllerTestSuite) SetupTest() { WithData(suite.T(), suite.apiWorkload). Write(suite.T(), resourceClient).Id + suite.apiServiceData = &pbcatalog.Service{ + Workloads: &pbcatalog.WorkloadSelector{Names: []string{"api-abc"}}, + VirtualIps: []string{"1.1.1.1"}, + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, + {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + } + suite.apiService = resourcetest.Resource(catalog.ServiceType, "api-service"). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"api-abc"}}, - VirtualIps: []string{"1.1.1.1"}, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - }}). + WithData(suite.T(), suite.apiServiceData). Write(suite.T(), suite.client.ResourceServiceClient) suite.apiEndpointsData = &pbcatalog.ServiceEndpoints{ @@ -267,20 +324,26 @@ func (suite *meshControllerTestSuite) TestController() { mgr := controller.NewManager(suite.client, suite.runtime.Logger) // Initialize controller dependencies. - destinationsCache := sidecarproxycache.NewDestinationsCache() - proxyCfgCache := sidecarproxycache.NewProxyConfigurationCache() - m := sidecarproxymapper.New(destinationsCache, proxyCfgCache) + var ( + destinationsCache = sidecarproxycache.NewDestinationsCache() + proxyCfgCache = sidecarproxycache.NewProxyConfigurationCache() + computedRoutesCache = sidecarproxycache.NewComputedRoutesCache() + m = sidecarproxymapper.New(destinationsCache, proxyCfgCache, computedRoutesCache) + ) trustDomainFetcher := func() (string, error) { return "test.consul", nil } - mgr.Register(Controller(destinationsCache, proxyCfgCache, m, trustDomainFetcher, "dc1")) + mgr.Register(Controller(destinationsCache, proxyCfgCache, computedRoutesCache, m, trustDomainFetcher, "dc1")) mgr.SetRaftLeader(true) go mgr.Run(suite.ctx) - // Create proxy state template IDs to check against in this test. - apiProxyStateTemplateID := resourcetest.Resource(types.ProxyStateTemplateType, "api-abc").ID() - webProxyStateTemplateID := resourcetest.Resource(types.ProxyStateTemplateType, "web-def").ID() - var ( + // Create proxy state template IDs to check against in this test. + apiProxyStateTemplateID = resourcetest.Resource(types.ProxyStateTemplateType, "api-abc").ID() + webProxyStateTemplateID = resourcetest.Resource(types.ProxyStateTemplateType, "web-def").ID() + + apiComputedRoutesID = resource.ReplaceType(types.ComputedRoutesType, suite.apiService.Id) + dbComputedRoutesID = resource.ReplaceType(types.ComputedRoutesType, suite.dbService.Id) + webProxyStateTemplate *pbresource.Resource webDestinations *pbresource.Resource ) @@ -294,6 +357,11 @@ func (suite *meshControllerTestSuite) TestController() { }) testutil.RunStep(suite.T(), "add explicit destinations and check that new proxy state is generated", func(t *testing.T) { + // Write a default ComputedRoutes for api. + routestest.ReconcileComputedRoutes(suite.T(), suite.client, apiComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](t, suite.apiService), + ) + // Add a source service and check that a new proxy state is generated. webDestinations = resourcetest.Resource(types.UpstreamsType, "web-destinations"). WithData(suite.T(), &pbmesh.Upstreams{ @@ -311,6 +379,7 @@ func (suite *meshControllerTestSuite) TestController() { }, }, }).Write(suite.T(), suite.client) + webProxyStateTemplate = suite.client.WaitForNewVersion(t, webProxyStateTemplateID, webProxyStateTemplate.Version) requireExplicitDestinationsFound(t, "api", webProxyStateTemplate) @@ -328,7 +397,7 @@ func (suite *meshControllerTestSuite) TestController() { // Note: the order matters here because in reality service endpoints will only // be reconciled after the workload has been updated, and so we need to write the - // workload before we write service endpoints. + // workload and service before we write service endpoints. resourcetest.Resource(catalog.WorkloadType, "api-abc"). WithData(suite.T(), &pbcatalog.Workload{ Identity: "api-identity", @@ -336,6 +405,17 @@ func (suite *meshControllerTestSuite) TestController() { Ports: nonMeshPorts}). Write(suite.T(), suite.client) + suite.apiService = resourcetest.ResourceID(suite.apiService.Id). + WithData(t, &pbcatalog.Service{ + Workloads: &pbcatalog.WorkloadSelector{Names: []string{"api-abc"}}, + VirtualIps: []string{"1.1.1.1"}, + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, + // {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + }). + Write(suite.T(), suite.client) + resourcetest.Resource(catalog.ServiceEndpointsType, "api-service"). WithData(suite.T(), &pbcatalog.ServiceEndpoints{ Endpoints: []*pbcatalog.Endpoint{ @@ -349,6 +429,11 @@ func (suite *meshControllerTestSuite) TestController() { }). Write(suite.T(), suite.client.ResourceServiceClient) + // Refresh the computed routes in light of api losing a mesh port. + routestest.ReconcileComputedRoutes(suite.T(), suite.client, apiComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](t, suite.apiService), + ) + // Check that api proxy template is gone. retry.Run(t, func(r *retry.R) { suite.client.RequireResourceNotFound(r, apiProxyStateTemplateID) @@ -369,14 +454,24 @@ func (suite *meshControllerTestSuite) TestController() { // Update destination's service endpoints back to mesh and check that we get a new web proxy resource re-generated // and that the status on Upstreams resource is updated to be empty. suite.runtime.Logger.Trace("updating ports to mesh") + resourcetest.Resource(catalog.WorkloadType, "api-abc"). WithData(suite.T(), suite.apiWorkload). Write(suite.T(), suite.client) + suite.apiService = resourcetest.Resource(catalog.ServiceType, "api-service"). + WithData(suite.T(), suite.apiServiceData). + Write(suite.T(), suite.client.ResourceServiceClient) + resourcetest.Resource(catalog.ServiceEndpointsType, "api-service"). WithData(suite.T(), suite.apiEndpointsData). Write(suite.T(), suite.client.ResourceServiceClient) + // Refresh the computed routes in light of api losing a mesh port. + routestest.ReconcileComputedRoutes(suite.T(), suite.client, apiComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](t, suite.apiService), + ) + serviceRef := resource.ReferenceToString(resource.Reference(suite.apiService.Id, "")) suite.client.WaitForStatusCondition(t, webDestinations.Id, ControllerName, status.ConditionMeshProtocolFound(serviceRef)) @@ -405,6 +500,12 @@ func (suite *meshControllerTestSuite) TestController() { webProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), webProxyStateTemplateID, webProxyStateTemplate.Version) + // Write a default ComputedRoutes for db, so it's eligible. + dbCR := routestest.ReconcileComputedRoutes(suite.T(), suite.client, dbComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](t, suite.dbService), + ) + require.NotNil(t, dbCR) + // Enable transparent proxy for the web proxy. resourcetest.Resource(types.ProxyConfigurationType, "proxy-config"). WithData(t, &pbmesh.ProxyConfiguration{ @@ -417,11 +518,63 @@ func (suite *meshControllerTestSuite) TestController() { OutboundListenerPort: 15001, }, }, - }).Write(t, suite.client) + }).Write(suite.T(), suite.client) webProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), webProxyStateTemplateID, webProxyStateTemplate.Version) requireImplicitDestinationsFound(t, "api", webProxyStateTemplate) + requireImplicitDestinationsFound(t, "db", webProxyStateTemplate) + }) + + testutil.RunStep(suite.T(), "add an HTTPRoute with a simple split on the tcp port", func(t *testing.T) { + // NOTE: because at this point we have tproxy in all-to-all mode, we will get an + // implicit upstream on 'db' + + // Create a route NOT in the state store, only to more easily feed + // into the generator. + routeData := &pbmesh.HTTPRoute{ + ParentRefs: []*pbmesh.ParentReference{{ + Ref: resource.Reference(suite.dbService.Id, ""), + Port: "", // implicitly applies to 'http' + }}, + Rules: []*pbmesh.HTTPRouteRule{{ + BackendRefs: []*pbmesh.HTTPBackendRef{ + { + BackendRef: &pbmesh.BackendReference{ + Ref: resource.Reference(suite.apiService.Id, ""), + Port: "tcp", + }, + Weight: 60, + }, + { + BackendRef: &pbmesh.BackendReference{ + Ref: resource.Reference(suite.dbService.Id, ""), + Port: "", // assumed to be 'http' + }, + Weight: 40, + }, + }, + }}, + } + route := resourcetest.Resource(types.HTTPRouteType, "db-http-route"). + WithData(t, routeData). + Build() + require.NoError(t, types.MutateHTTPRoute(route)) + require.NoError(t, types.ValidateHTTPRoute(route)) + + dbCRID := resource.ReplaceType(types.ComputedRoutesType, suite.dbService.Id) + + dbCR := routestest.ReconcileComputedRoutes(suite.T(), suite.client, dbCRID, + resourcetest.MustDecode[*pbmesh.HTTPRoute](t, route), + resourcetest.MustDecode[*pbcatalog.Service](t, suite.dbService), + resourcetest.MustDecode[*pbcatalog.Service](t, suite.apiService), + ) + require.NotNil(t, dbCR, "computed routes for db was deleted instead of created") + + webProxyStateTemplate = suite.client.WaitForNewVersion(t, webProxyStateTemplateID, webProxyStateTemplate.Version) + + requireImplicitDestinationsFound(t, "api", webProxyStateTemplate) + requireImplicitDestinationsFound(t, "db", webProxyStateTemplate) }) } @@ -473,8 +626,23 @@ func requireImplicitDestinationsFound(t *testing.T, name string, tmplResource *p // Check the listener filter chain for _, r := range l.Routers { - destName := r.Destination.(*pbproxystate.Router_L4).L4.Name - if strings.Contains(destName, name) { + foundByName := false + switch x := r.Destination.(type) { + case *pbproxystate.Router_L4: + // TcpProxy is easy, so just having this exist is + // sufficient. We don't have to deep inspect it. We care + // that there IS a listener matching the destination. If + // there is a TCPRoute with a split or a rename we don't + // care here. + foundByName = true + case *pbproxystate.Router_L7: + routerName := x.L7.Name + foundByName = strings.Contains(routerName, name) + default: + t.Fatalf("unexpected type of destination: %T", r.Destination) + } + + if foundByName { // We expect that there is a filter chain match for transparent proxy destinations. require.NotNil(t, r.Match) require.NotEmpty(t, r.Match.PrefixRanges) diff --git a/internal/mesh/internal/controllers/sidecarproxy/fetcher/data_fetcher.go b/internal/mesh/internal/controllers/sidecarproxy/fetcher/data_fetcher.go index 7462fba7021c..a61c74a2dbb7 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/fetcher/data_fetcher.go +++ b/internal/mesh/internal/controllers/sidecarproxy/fetcher/data_fetcher.go @@ -5,6 +5,8 @@ package fetcher import ( "context" + "fmt" + "strings" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -16,158 +18,84 @@ import ( "github.com/hashicorp/consul/internal/mesh/internal/types" intermediateTypes "github.com/hashicorp/consul/internal/mesh/internal/types/intermediate" "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/storage" pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" "github.com/hashicorp/consul/proto-public/pbresource" ) type Fetcher struct { - Client pbresource.ResourceServiceClient - DestinationsCache *sidecarproxycache.DestinationsCache - ProxyCfgCache *sidecarproxycache.ProxyConfigurationCache + Client pbresource.ResourceServiceClient + DestinationsCache *sidecarproxycache.DestinationsCache + ProxyCfgCache *sidecarproxycache.ProxyConfigurationCache + ComputedRoutesCache *sidecarproxycache.ComputedRoutesCache } -func New(client pbresource.ResourceServiceClient, +func New( + client pbresource.ResourceServiceClient, dCache *sidecarproxycache.DestinationsCache, - pcfgCache *sidecarproxycache.ProxyConfigurationCache) *Fetcher { - + pcfgCache *sidecarproxycache.ProxyConfigurationCache, + computedRoutesCache *sidecarproxycache.ComputedRoutesCache, +) *Fetcher { return &Fetcher{ - Client: client, - DestinationsCache: dCache, - ProxyCfgCache: pcfgCache, + Client: client, + DestinationsCache: dCache, + ProxyCfgCache: pcfgCache, + ComputedRoutesCache: computedRoutesCache, } } -func (f *Fetcher) FetchWorkload(ctx context.Context, id *pbresource.ID) (*intermediateTypes.Workload, error) { - rsp, err := f.Client.Read(ctx, &pbresource.ReadRequest{Id: id}) - - switch { - case status.Code(err) == codes.NotFound: +func (f *Fetcher) FetchWorkload(ctx context.Context, id *pbresource.ID) (*types.DecodedWorkload, error) { + dec, err := resource.GetDecodedResource[*pbcatalog.Workload](ctx, f.Client, id) + if err != nil { + return nil, err + } else if dec == nil { // We also need to make sure to delete the associated proxy from cache. // We are ignoring errors from cache here as this deletion is best effort. proxyID := resource.ReplaceType(types.ProxyStateTemplateType, id) f.DestinationsCache.DeleteSourceProxy(proxyID) f.ProxyCfgCache.UntrackProxyID(proxyID) return nil, nil - case err != nil: - return nil, err - } - - w := &intermediateTypes.Workload{ - Resource: rsp.Resource, - } - - var workload pbcatalog.Workload - err = rsp.Resource.Data.UnmarshalTo(&workload) - if err != nil { - return nil, resource.NewErrDataParse(&workload, err) } - w.Workload = &workload - return w, nil + return dec, err } -func (f *Fetcher) FetchProxyStateTemplate(ctx context.Context, id *pbresource.ID) (*intermediateTypes.ProxyStateTemplate, error) { - rsp, err := f.Client.Read(ctx, &pbresource.ReadRequest{Id: id}) - - switch { - case status.Code(err) == codes.NotFound: - return nil, nil - case err != nil: - return nil, err - } - - p := &intermediateTypes.ProxyStateTemplate{ - Resource: rsp.Resource, - } - - var tmpl pbmesh.ProxyStateTemplate - err = rsp.Resource.Data.UnmarshalTo(&tmpl) - if err != nil { - return nil, resource.NewErrDataParse(&tmpl, err) - } - - p.Tmpl = &tmpl - return p, nil +func (f *Fetcher) FetchProxyStateTemplate(ctx context.Context, id *pbresource.ID) (*types.DecodedProxyStateTemplate, error) { + return resource.GetDecodedResource[*pbmesh.ProxyStateTemplate](ctx, f.Client, id) } -func (f *Fetcher) FetchServiceEndpoints(ctx context.Context, id *pbresource.ID) (*intermediateTypes.ServiceEndpoints, error) { - rsp, err := f.Client.Read(ctx, &pbresource.ReadRequest{Id: id}) - - switch { - case status.Code(err) == codes.NotFound: - return nil, nil - case err != nil: - return nil, err - } - - se := &intermediateTypes.ServiceEndpoints{ - Resource: rsp.Resource, - } - - var endpoints pbcatalog.ServiceEndpoints - err = rsp.Resource.Data.UnmarshalTo(&endpoints) - if err != nil { - return nil, resource.NewErrDataParse(&endpoints, err) - } - - se.Endpoints = &endpoints - return se, nil +func (f *Fetcher) FetchServiceEndpoints(ctx context.Context, id *pbresource.ID) (*types.DecodedServiceEndpoints, error) { + return resource.GetDecodedResource[*pbcatalog.ServiceEndpoints](ctx, f.Client, id) } -func (f *Fetcher) FetchService(ctx context.Context, id *pbresource.ID) (*intermediateTypes.Service, error) { - rsp, err := f.Client.Read(ctx, &pbresource.ReadRequest{Id: id}) - - switch { - case status.Code(err) == codes.NotFound: - return nil, nil - case err != nil: - return nil, err - } - - se := &intermediateTypes.Service{ - Resource: rsp.Resource, - } - - var service pbcatalog.Service - err = rsp.Resource.Data.UnmarshalTo(&service) - if err != nil { - return nil, resource.NewErrDataParse(&service, err) - } - - se.Service = &service - return se, nil +func (f *Fetcher) FetchService(ctx context.Context, id *pbresource.ID) (*types.DecodedService, error) { + return resource.GetDecodedResource[*pbcatalog.Service](ctx, f.Client, id) } -func (f *Fetcher) FetchDestinations(ctx context.Context, id *pbresource.ID) (*intermediateTypes.Destinations, error) { - rsp, err := f.Client.Read(ctx, &pbresource.ReadRequest{Id: id}) - - switch { - case status.Code(err) == codes.NotFound: - return nil, nil - case err != nil: - return nil, err - } +func (f *Fetcher) FetchDestinations(ctx context.Context, id *pbresource.ID) (*types.DecodedDestinations, error) { + return resource.GetDecodedResource[*pbmesh.Upstreams](ctx, f.Client, id) +} - u := &intermediateTypes.Destinations{ - Resource: rsp.Resource, +func (f *Fetcher) FetchComputedRoutes(ctx context.Context, id *pbresource.ID) (*types.DecodedComputedRoutes, error) { + if !types.IsComputedRoutesType(id.Type) { + return nil, fmt.Errorf("id must be a ComputedRoutes type") } - var destinations pbmesh.Upstreams - err = rsp.Resource.Data.UnmarshalTo(&destinations) + dec, err := resource.GetDecodedResource[*pbmesh.ComputedRoutes](ctx, f.Client, id) if err != nil { - return nil, resource.NewErrDataParse(&destinations, err) + return nil, err + } else if dec == nil { + f.ComputedRoutesCache.UntrackComputedRoutes(id) } - u.Destinations = &destinations - return u, nil + return dec, err } func (f *Fetcher) FetchExplicitDestinationsData( ctx context.Context, explDestRefs []intermediateTypes.CombinedDestinationRef, ) ([]*intermediateTypes.Destination, map[string]*intermediateTypes.Status, error) { - var ( destinations []*intermediateTypes.Destination statuses = make(map[string]*intermediateTypes.Status) @@ -190,22 +118,22 @@ func (f *Fetcher) FetchExplicitDestinationsData( d := &intermediateTypes.Destination{} - // As Destinations resource contains a list of destinations, - // we need to find the one that references our service and port. - d.Explicit = findDestination(dest.ServiceRef, dest.Port, us.Destinations) + var ( + serviceID = resource.IDFromReference(dest.ServiceRef) + serviceRef = resource.ReferenceToString(dest.ServiceRef) + upstreamsRef = resource.IDToString(us.Resource.Id) + ) - // Fetch ServiceEndpoints. - serviceID := resource.IDFromReference(dest.ServiceRef) - se, err := f.FetchServiceEndpoints(ctx, resource.ReplaceType(catalog.ServiceEndpointsType, serviceID)) + // Fetch Service + svc, err := f.FetchService(ctx, serviceID) if err != nil { return nil, statuses, err } - serviceRef := resource.ReferenceToString(dest.ServiceRef) - upstreamsRef := resource.IDToString(us.Resource.Id) - if se == nil { - // If the Service Endpoints resource is not found, then we update the status of the Upstreams resource - // but don't remove it from cache in case it comes back. + if svc == nil { + // If the Service resource is not found, then we update the status + // of the Upstreams resource but don't remove it from cache in case + // it comes back. updateStatusCondition(statuses, upstreamsRef, dest.ExplicitDestinationsID, us.Resource.Status, us.Resource.Generation, ctrlStatus.ConditionDestinationServiceNotFound(serviceRef)) continue @@ -214,10 +142,10 @@ func (f *Fetcher) FetchExplicitDestinationsData( us.Resource.Status, us.Resource.Generation, ctrlStatus.ConditionDestinationServiceFound(serviceRef)) } - d.ServiceEndpoints = se + d.Service = svc // Check if this endpoints is mesh-enabled. If not, remove it from cache and return an error. - if len(se.Endpoints.Endpoints) > 0 && !IsMeshEnabled(se.Endpoints.Endpoints[0].Ports) { + if !IsMeshEnabled(svc.Data.Ports) { // Add invalid status but don't remove from cache. If this state changes, // we want to be able to detect this change. updateStatusCondition(statuses, upstreamsRef, dest.ExplicitDestinationsID, @@ -234,9 +162,7 @@ func (f *Fetcher) FetchExplicitDestinationsData( // No destination port should point to a port with "mesh" protocol, // so check if destination port has the mesh protocol and update the status. - if len(se.Endpoints.Endpoints) > 0 && - se.Endpoints.Endpoints[0].Ports[dest.Port].Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - + if isServicePortMeshProtocol(svc.Data.Ports, dest.Port) { updateStatusCondition(statuses, upstreamsRef, dest.ExplicitDestinationsID, us.Resource.Status, us.Resource.Generation, ctrlStatus.ConditionMeshProtocolDestinationPort(serviceRef, dest.Port)) continue @@ -245,16 +171,67 @@ func (f *Fetcher) FetchExplicitDestinationsData( us.Resource.Status, us.Resource.Generation, ctrlStatus.ConditionNonMeshProtocolDestinationPort(serviceRef, dest.Port)) } - // Gather all identities. - if se != nil { - var identities []*pbresource.Reference - for _, ep := range se.Endpoints.Endpoints { - identities = append(identities, &pbresource.Reference{ - Name: ep.Identity, - Tenancy: se.Resource.Id.Tenancy, - }) + // Fetch ComputedRoutes. + cr, err := f.FetchComputedRoutes(ctx, resource.ReplaceType(types.ComputedRoutesType, serviceID)) + if err != nil { + return nil, statuses, err + } else if cr == nil { + // This is required, so wait until it exists. + updateStatusCondition(statuses, upstreamsRef, dest.ExplicitDestinationsID, + us.Resource.Status, us.Resource.Generation, + ctrlStatus.ConditionDestinationComputedRoutesNotFound(serviceRef)) + continue + } else { + updateStatusCondition(statuses, upstreamsRef, dest.ExplicitDestinationsID, + us.Resource.Status, us.Resource.Generation, + ctrlStatus.ConditionDestinationComputedRoutesFound(serviceRef)) + } + + portConfig, ok := cr.Data.PortedConfigs[dest.Port] + if !ok { + // This is required, so wait until it exists. + updateStatusCondition(statuses, upstreamsRef, dest.ExplicitDestinationsID, + us.Resource.Status, us.Resource.Generation, + ctrlStatus.ConditionDestinationComputedRoutesPortNotFound(serviceRef, dest.Port)) + continue + } else { + updateStatusCondition(statuses, upstreamsRef, dest.ExplicitDestinationsID, + us.Resource.Status, us.Resource.Generation, + ctrlStatus.ConditionDestinationComputedRoutesPortFound(serviceRef, dest.Port)) + } + // Copy this so we can mutate the targets. + d.ComputedPortRoutes = proto.Clone(portConfig).(*pbmesh.ComputedPortRoutes) + + // As Destinations resource contains a list of destinations, + // we need to find the one that references our service and port. + d.Explicit = findDestination(dest.ServiceRef, dest.Port, us.Data) + if d.Explicit == nil { + continue // the cache is out of sync + } + + for _, routeTarget := range d.ComputedPortRoutes.Targets { + targetServiceID := resource.IDFromReference(routeTarget.BackendRef.Ref) + + // Fetch ServiceEndpoints. + se, err := f.FetchServiceEndpoints(ctx, resource.ReplaceType(catalog.ServiceEndpointsType, targetServiceID)) + if err != nil { + return nil, statuses, err + } + + if se != nil { + routeTarget.ServiceEndpointsId = se.Resource.Id + routeTarget.ServiceEndpoints = se.Data + + // Gather all identities. + var identities []*pbresource.Reference + for _, ep := range se.Data.Endpoints { + identities = append(identities, &pbresource.Reference{ + Name: ep.Identity, + Tenancy: se.Resource.Id.Tenancy, + }) + } + routeTarget.IdentityRefs = identities } - d.Identities = identities } destinations = append(destinations, d) @@ -263,21 +240,37 @@ func (f *Fetcher) FetchExplicitDestinationsData( return destinations, statuses, nil } +type PortReferenceKey struct { + resource.ReferenceKey + Port string +} + // FetchImplicitDestinationsData fetches all implicit destinations and adds them to existing destinations. // If the implicit destination is already in addToDestinations, it will be skipped. // todo (ishustava): this function will eventually need to fetch implicit destinations from the ImplicitDestinations resource instead. -func (f *Fetcher) FetchImplicitDestinationsData(ctx context.Context, proxyID *pbresource.ID, addToDestinations []*intermediateTypes.Destination) ([]*intermediateTypes.Destination, error) { +func (f *Fetcher) FetchImplicitDestinationsData( + ctx context.Context, + proxyID *pbresource.ID, + addToDestinations []*intermediateTypes.Destination, +) ([]*intermediateTypes.Destination, error) { // First, convert existing destinations to a map so we can de-dup. - destinations := make(map[resource.ReferenceKey]*intermediateTypes.Destination) + // + // This is keyed by the serviceID+port of the upstream, which is effectively + // the same as the id of the computed routes for the service. + destinations := make(map[PortReferenceKey]*intermediateTypes.Destination) for _, d := range addToDestinations { - destinations[resource.NewReferenceKey(d.ServiceEndpoints.Resource.Id)] = d + prk := PortReferenceKey{ + ReferenceKey: resource.NewReferenceKey(d.Service.Resource.Id), + Port: d.ComputedPortRoutes.ParentRef.Port, + } + destinations[prk] = d } - // For now, we need to look up all service endpoints within a partition. + // For now we need to look up all computed routes within a partition. rsp, err := f.Client.List(ctx, &pbresource.ListRequest{ - Type: catalog.ServiceEndpointsType, + Type: types.ComputedRoutesType, Tenancy: &pbresource.Tenancy{ - Namespace: proxyID.Tenancy.Namespace, + Namespace: storage.Wildcard, Partition: proxyID.Tenancy.Partition, PeerName: proxyID.Tenancy.PeerName, }, @@ -287,56 +280,106 @@ func (f *Fetcher) FetchImplicitDestinationsData(ctx context.Context, proxyID *pb } for _, r := range rsp.Resources { - // If it's already in destinations, ignore it. - if _, ok := destinations[resource.NewReferenceKey(r.Id)]; ok { + svcID := resource.ReplaceType(catalog.ServiceType, r.Id) + computedRoutes, err := resource.Decode[*pbmesh.ComputedRoutes](r) + if err != nil { + return nil, err + } + + if computedRoutes == nil { + // the routes-controller doesn't deem this worthy of the mesh continue } - var endpoints pbcatalog.ServiceEndpoints - err = r.Data.UnmarshalTo(&endpoints) + // Fetch the service. + // todo (ishustava): this should eventually grab virtual IPs resource. + svc, err := f.FetchService(ctx, resource.ReplaceType(catalog.ServiceType, r.Id)) if err != nil { return nil, err } - - // If this proxy is a part of this service, ignore it. - if isPartOfService(resource.ReplaceType(catalog.WorkloadType, proxyID), &endpoints) { + if svc == nil { + // If service no longer exists, skip. continue } - // Skip if this service is not mesh-enabled. - if len(endpoints.Endpoints) > 0 && !IsMeshEnabled(endpoints.Endpoints[0].Ports) { + // If this proxy is a part of this service, ignore it. + if isPartOfService(resource.ReplaceType(catalog.WorkloadType, proxyID), svc) { continue } - // Collect all identities. - var identities []*pbresource.Reference - for _, ep := range endpoints.Endpoints { - identities = append(identities, &pbresource.Reference{ - Name: ep.Identity, - Tenancy: r.Id.Tenancy, - }) + inMesh := false + for _, port := range svc.Data.Ports { + if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { + inMesh = true + break + } } - // Fetch the service. - // todo (ishustava): this should eventually grab virtual IPs resource. - s, err := f.FetchService(ctx, resource.ReplaceType(catalog.ServiceType, r.Id)) - if err != nil { - return nil, err - } - if s == nil { - // If service no longer exists, skip. + if !inMesh { + // If a service is no longer in the mesh, skip. continue } - d := &intermediateTypes.Destination{ - ServiceEndpoints: &intermediateTypes.ServiceEndpoints{ - Resource: r, - Endpoints: &endpoints, - }, - VirtualIPs: s.Service.VirtualIps, - Identities: identities, + // Fetch the resources that may show up duplicated. + endpointsMap := make(map[resource.ReferenceKey]*types.DecodedServiceEndpoints) + for _, portConfig := range computedRoutes.Data.PortedConfigs { + for _, routeTarget := range portConfig.Targets { + targetServiceID := resource.IDFromReference(routeTarget.BackendRef.Ref) + + seID := resource.ReplaceType(catalog.ServiceEndpointsType, targetServiceID) + seRK := resource.NewReferenceKey(seID) + + if _, ok := endpointsMap[seRK]; !ok { + se, err := f.FetchServiceEndpoints(ctx, seID) + if err != nil { + return nil, err + } + endpointsMap[seRK] = se + } + } + } + + for portName, portConfig := range computedRoutes.Data.PortedConfigs { + // If it's already in destinations, ignore it. + prk := PortReferenceKey{ + ReferenceKey: resource.NewReferenceKey(svcID), + Port: portName, + } + if _, ok := destinations[prk]; ok { + continue + } + + // Copy this so we can mutate the targets. + portConfig = proto.Clone(portConfig).(*pbmesh.ComputedPortRoutes) + + d := &intermediateTypes.Destination{ + Service: svc, + ComputedPortRoutes: portConfig, + VirtualIPs: svc.Data.VirtualIps, + } + for _, routeTarget := range portConfig.Targets { + targetServiceID := resource.IDFromReference(routeTarget.BackendRef.Ref) + seID := resource.ReplaceType(catalog.ServiceEndpointsType, targetServiceID) + + // Fetch ServiceEndpoints. + se, ok := endpointsMap[resource.NewReferenceKey(seID)] + if ok { + routeTarget.ServiceEndpointsId = se.Resource.Id + routeTarget.ServiceEndpoints = se.Data + + // Gather all identities. + var identities []*pbresource.Reference + for _, ep := range se.Data.Endpoints { + identities = append(identities, &pbresource.Reference{ + Name: ep.Identity, + Tenancy: se.Resource.Id.Tenancy, + }) + } + routeTarget.IdentityRefs = identities + } + } + addToDestinations = append(addToDestinations, d) } - addToDestinations = append(addToDestinations, d) } return addToDestinations, err } @@ -381,9 +424,20 @@ func (f *Fetcher) FetchAndMergeProxyConfigurations(ctx context.Context, id *pbre return result, nil } -// IsMeshEnabled returns true if the workload or service endpoints port +// IsWorkloadMeshEnabled returns true if the workload or service endpoints port // contain a port with the "mesh" protocol. -func IsMeshEnabled(ports map[string]*pbcatalog.WorkloadPort) bool { +func IsWorkloadMeshEnabled(ports map[string]*pbcatalog.WorkloadPort) bool { + for _, port := range ports { + if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { + return true + } + } + return false +} + +// IsMeshEnabled returns true if the service ports contain a port with the +// "mesh" protocol. +func IsMeshEnabled(ports []*pbcatalog.ServicePort) bool { for _, port := range ports { if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { return true @@ -392,6 +446,20 @@ func IsMeshEnabled(ports map[string]*pbcatalog.WorkloadPort) bool { return false } +func isServicePortMeshProtocol(ports []*pbcatalog.ServicePort, name string) bool { + sp := findServicePort(ports, name) + return sp != nil && sp.Protocol == pbcatalog.Protocol_PROTOCOL_MESH +} + +func findServicePort(ports []*pbcatalog.ServicePort, name string) *pbcatalog.ServicePort { + for _, port := range ports { + if port.TargetPort == name { + return port + } + } + return nil +} + func findDestination(ref *pbresource.Reference, port string, destinations *pbmesh.Upstreams) *pbmesh.Upstream { for _, destination := range destinations.Upstreams { if resource.EqualReference(ref, destination.DestinationRef) && @@ -421,15 +489,19 @@ func updateStatusCondition( } } -func isPartOfService(workloadID *pbresource.ID, endpoints *pbcatalog.ServiceEndpoints) bool { - // convert IDs to refs so that we can compare without UIDs. - workloadRef := resource.Reference(workloadID, "") - for _, ep := range endpoints.Endpoints { - if ep.TargetRef != nil { - targetRef := resource.Reference(ep.TargetRef, "") - if resource.EqualReference(workloadRef, targetRef) { - return true - } +func isPartOfService(workloadID *pbresource.ID, svc *types.DecodedService) bool { + if !resource.EqualTenancy(workloadID.GetTenancy(), svc.Resource.Id.GetTenancy()) { + return false + } + sel := svc.Data.Workloads + for _, exact := range sel.GetNames() { + if workloadID.GetName() == exact { + return true + } + } + for _, prefix := range sel.GetPrefixes() { + if strings.HasPrefix(workloadID.GetName(), prefix) { + return true } } return false diff --git a/internal/mesh/internal/controllers/sidecarproxy/fetcher/data_fetcher_test.go b/internal/mesh/internal/controllers/sidecarproxy/fetcher/data_fetcher_test.go index d4a9e7de8406..adbf431e148b 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/fetcher/data_fetcher_test.go +++ b/internal/mesh/internal/controllers/sidecarproxy/fetcher/data_fetcher_test.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/consul/internal/catalog" "github.com/hashicorp/consul/internal/controller" "github.com/hashicorp/consul/internal/mesh/internal/cache/sidecarproxycache" + "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/routestest" meshStatus "github.com/hashicorp/consul/internal/mesh/internal/controllers/sidecarproxy/status" "github.com/hashicorp/consul/internal/mesh/internal/types" "github.com/hashicorp/consul/internal/mesh/internal/types/intermediate" @@ -29,6 +30,52 @@ import ( ) func TestIsMeshEnabled(t *testing.T) { + cases := map[string]struct { + ports []*pbcatalog.ServicePort + exp bool + }{ + "nil ports": { + ports: nil, + exp: false, + }, + "empty ports": { + ports: []*pbcatalog.ServicePort{}, + exp: false, + }, + "no mesh ports": { + ports: []*pbcatalog.ServicePort{ + {VirtualPort: 1000, TargetPort: "p1", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + {VirtualPort: 2000, TargetPort: "p2", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, + }, + exp: false, + }, + "one mesh port": { + ports: []*pbcatalog.ServicePort{ + {VirtualPort: 1000, TargetPort: "p1", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + {VirtualPort: 2000, TargetPort: "p2", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, + {VirtualPort: 3000, TargetPort: "p3", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + exp: true, + }, + "multiple mesh ports": { + ports: []*pbcatalog.ServicePort{ + {VirtualPort: 1000, TargetPort: "p1", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + {VirtualPort: 2000, TargetPort: "p2", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, + {VirtualPort: 3000, TargetPort: "p3", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + {VirtualPort: 4000, TargetPort: "p4", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + exp: true, + }, + } + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + require.Equal(t, c.exp, IsMeshEnabled(c.ports)) + }) + } +} + +func TestIsWorkloadMeshEnabled(t *testing.T) { cases := map[string]struct { ports map[string]*pbcatalog.WorkloadPort exp bool @@ -69,7 +116,7 @@ func TestIsMeshEnabled(t *testing.T) { for name, c := range cases { t.Run(name, func(t *testing.T) { - require.Equal(t, c.exp, IsMeshEnabled(c.ports)) + require.Equal(t, c.exp, IsWorkloadMeshEnabled(c.ports)) }) } } @@ -82,7 +129,9 @@ type dataFetcherSuite struct { rt controller.Runtime api1Service *pbresource.Resource + api1ServiceData *pbcatalog.Service api2Service *pbresource.Resource + api2ServiceData *pbcatalog.Service api1ServiceEndpoints *pbresource.Resource api1ServiceEndpointsData *pbcatalog.ServiceEndpoints api2ServiceEndpoints *pbresource.Resource @@ -101,8 +150,14 @@ func (suite *dataFetcherSuite) SetupTest() { Logger: testutil.Logger(suite.T()), } + suite.api1ServiceData = &pbcatalog.Service{ + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "tcp", VirtualPort: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, + {TargetPort: "mesh", VirtualPort: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + } suite.api1Service = resourcetest.Resource(catalog.ServiceType, "api-1"). - WithData(suite.T(), &pbcatalog.Service{}). + WithData(suite.T(), suite.api1ServiceData). Write(suite.T(), suite.client) suite.api1ServiceEndpointsData = &pbcatalog.ServiceEndpoints{ @@ -111,17 +166,25 @@ func (suite *dataFetcherSuite) SetupTest() { Addresses: []*pbcatalog.WorkloadAddress{{Host: "10.0.0.1"}}, Ports: map[string]*pbcatalog.WorkloadPort{ "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, }, Identity: "api-1-identity", }, }, } suite.api1ServiceEndpoints = resourcetest.Resource(catalog.ServiceEndpointsType, "api-1"). - WithData(suite.T(), suite.api1ServiceEndpointsData).Write(suite.T(), suite.client) + WithData(suite.T(), suite.api1ServiceEndpointsData). + Write(suite.T(), suite.client) + suite.api2ServiceData = &pbcatalog.Service{ + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "tcp1", VirtualPort: 9080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, + {TargetPort: "tcp2", VirtualPort: 9081, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, + {TargetPort: "mesh", VirtualPort: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + } suite.api2Service = resourcetest.Resource(catalog.ServiceType, "api-2"). - WithData(suite.T(), &pbcatalog.Service{}). + WithData(suite.T(), suite.api2ServiceData). Write(suite.T(), suite.client) suite.api2ServiceEndpointsData = &pbcatalog.ServiceEndpoints{ @@ -138,7 +201,8 @@ func (suite *dataFetcherSuite) SetupTest() { }, } suite.api2ServiceEndpoints = resourcetest.Resource(catalog.ServiceEndpointsType, "api-2"). - WithData(suite.T(), suite.api2ServiceEndpointsData).Write(suite.T(), suite.client) + WithData(suite.T(), suite.api2ServiceEndpointsData). + Write(suite.T(), suite.client) suite.webDestinationsData = &pbmesh.Upstreams{ Upstreams: []*pbmesh.Upstream{ @@ -179,8 +243,11 @@ func (suite *dataFetcherSuite) TestFetcher_FetchWorkload_WorkloadNotFound() { proxyID := resourcetest.Resource(types.ProxyStateTemplateType, "service-workload-abc").ID() // Create cache and pre-populate it. - destCache := sidecarproxycache.NewDestinationsCache() - proxyCfgCache := sidecarproxycache.NewProxyConfigurationCache() + var ( + destCache = sidecarproxycache.NewDestinationsCache() + proxyCfgCache = sidecarproxycache.NewProxyConfigurationCache() + computedRoutesCache = sidecarproxycache.NewComputedRoutesCache() + ) dest1 := intermediate.CombinedDestinationRef{ ServiceRef: resourcetest.Resource(catalog.ServiceType, "test-service-1").ReferenceNoSection(), Port: "tcp", @@ -199,11 +266,13 @@ func (suite *dataFetcherSuite) TestFetcher_FetchWorkload_WorkloadNotFound() { } destCache.WriteDestination(dest1) destCache.WriteDestination(dest2) + suite.syncDestinations(dest1, dest2) proxyCfgID := resourcetest.Resource(types.ProxyConfigurationType, "proxy-config").ID() proxyCfgCache.TrackProxyConfiguration(proxyCfgID, []resource.ReferenceOrID{proxyID}) - f := Fetcher{DestinationsCache: destCache, ProxyCfgCache: proxyCfgCache, Client: suite.client} + f := New(suite.client, destCache, proxyCfgCache, computedRoutesCache) + _, err := f.FetchWorkload(context.Background(), proxyID) require.NoError(suite.T(), err) @@ -335,45 +404,46 @@ func (suite *dataFetcherSuite) TestFetcher_FetchErrors() { } } -func (suite *dataFetcherSuite) TestFetcher_FetchExplicitDestinationsData() { - destination1 := intermediate.CombinedDestinationRef{ - ServiceRef: resource.Reference(suite.api1Service.Id, ""), - Port: "tcp", - ExplicitDestinationsID: suite.webDestinations.Id, - SourceProxies: map[resource.ReferenceKey]struct{}{ - resource.NewReferenceKey(suite.webProxy.Id): {}, - }, - } - destination2 := intermediate.CombinedDestinationRef{ - ServiceRef: resource.Reference(suite.api2Service.Id, ""), - Port: "tcp1", - ExplicitDestinationsID: suite.webDestinations.Id, - SourceProxies: map[resource.ReferenceKey]struct{}{ - resource.NewReferenceKey(suite.webProxy.Id): {}, - }, +func (suite *dataFetcherSuite) syncDestinations(destinations ...intermediate.CombinedDestinationRef) { + data := &pbmesh.Upstreams{} + for _, dest := range destinations { + data.Upstreams = append(data.Upstreams, &pbmesh.Upstream{ + DestinationRef: dest.ServiceRef, + DestinationPort: dest.Port, + }) } - destination3 := intermediate.CombinedDestinationRef{ - ServiceRef: resource.Reference(suite.api2Service.Id, ""), - Port: "tcp2", - ExplicitDestinationsID: suite.webDestinations.Id, - SourceProxies: map[resource.ReferenceKey]struct{}{ - resource.NewReferenceKey(suite.webProxy.Id): {}, - }, + + suite.webDestinations = resourcetest.Resource(types.UpstreamsType, "web-destinations"). + WithData(suite.T(), data). + Write(suite.T(), suite.client) +} + +func (suite *dataFetcherSuite) TestFetcher_FetchExplicitDestinationsData() { + var ( + c = sidecarproxycache.NewDestinationsCache() + crCache = sidecarproxycache.NewComputedRoutesCache() + ) + + writeDestination := func(t *testing.T, dest intermediate.CombinedDestinationRef) { + c.WriteDestination(dest) + t.Cleanup(func() { + c.DeleteDestination(dest.ServiceRef, dest.Port) + }) } - c := sidecarproxycache.NewDestinationsCache() - c.WriteDestination(destination1) - c.WriteDestination(destination2) - c.WriteDestination(destination3) + var ( + api1ServiceRef = resource.Reference(suite.api1Service.Id, "") + ) f := Fetcher{ - DestinationsCache: c, - Client: suite.client, + DestinationsCache: c, + ComputedRoutesCache: crCache, + Client: suite.client, } - suite.T().Run("destinations not found", func(t *testing.T) { + testutil.RunStep(suite.T(), "invalid destinations: destinations not found", func(t *testing.T) { destinationRefNoDestinations := intermediate.CombinedDestinationRef{ - ServiceRef: resource.Reference(suite.api1Service.Id, ""), + ServiceRef: api1ServiceRef, Port: "tcp", ExplicitDestinationsID: resourcetest.Resource(types.UpstreamsType, "not-found").ID(), SourceProxies: map[resource.ReferenceKey]struct{}{ @@ -381,6 +451,7 @@ func (suite *dataFetcherSuite) TestFetcher_FetchExplicitDestinationsData() { }, } c.WriteDestination(destinationRefNoDestinations) + suite.syncDestinations(destinationRefNoDestinations) destinationRefs := []intermediate.CombinedDestinationRef{destinationRefNoDestinations} destinations, _, err := f.FetchExplicitDestinationsData(suite.ctx, destinationRefs) @@ -390,7 +461,7 @@ func (suite *dataFetcherSuite) TestFetcher_FetchExplicitDestinationsData() { require.False(t, foundDest) }) - suite.T().Run("service endpoints not found", func(t *testing.T) { + testutil.RunStep(suite.T(), "invalid destinations: service not found", func(t *testing.T) { notFoundServiceRef := resourcetest.Resource(catalog.ServiceType, "not-found"). WithTenancy(resource.DefaultNamespacedTenancy()). ReferenceNoSection() @@ -403,39 +474,53 @@ func (suite *dataFetcherSuite) TestFetcher_FetchExplicitDestinationsData() { }, } c.WriteDestination(destinationNoServiceEndpoints) + suite.syncDestinations(destinationNoServiceEndpoints) + + t.Cleanup(func() { + // Restore this for the next test step. + suite.webDestinations = resourcetest.Resource(types.UpstreamsType, "web-destinations"). + WithData(suite.T(), suite.webDestinationsData). + Write(suite.T(), suite.client) + }) + suite.webDestinations = resourcetest.Resource(types.UpstreamsType, "web-destinations"). + WithData(suite.T(), &pbmesh.Upstreams{ + Upstreams: []*pbmesh.Upstream{{ + DestinationRef: notFoundServiceRef, + DestinationPort: "tcp", + }}, + }). + Write(suite.T(), suite.client) destinationRefs := []intermediate.CombinedDestinationRef{destinationNoServiceEndpoints} destinations, statuses, err := f.FetchExplicitDestinationsData(suite.ctx, destinationRefs) require.NoError(t, err) - require.Nil(t, destinations) + require.Empty(t, destinations) destinationRef := resource.IDToString(destinationNoServiceEndpoints.ExplicitDestinationsID) serviceRef := resource.ReferenceToString(destinationNoServiceEndpoints.ServiceRef) - require.Len(t, statuses[destinationRef].Conditions, 1) - require.Equal(t, statuses[destinationRef].Conditions[0], + destStatus, exists := statuses[destinationRef] + require.True(t, exists, "status map does not contain service: %s", destinationRef) + + require.Len(t, destStatus.Conditions, 1) + require.Equal(t, destStatus.Conditions[0], meshStatus.ConditionDestinationServiceNotFound(serviceRef)) _, foundDest := c.ReadDestination(destinationNoServiceEndpoints.ServiceRef, destinationNoServiceEndpoints.Port) require.True(t, foundDest) }) - suite.T().Run("service endpoints not on mesh", func(t *testing.T) { - apiNonMeshServiceEndpointsData := &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - Addresses: []*pbcatalog.WorkloadAddress{{Host: "10.0.0.1"}}, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - }, - Identity: "api-1-identity", - }, + testutil.RunStep(suite.T(), "invalid destinations: service not on mesh", func(t *testing.T) { + apiNonMeshServiceData := &pbcatalog.Service{ + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, }, } - apiNonMeshServiceEndpoints := resourcetest.Resource(catalog.ServiceEndpointsType, "api-1"). - WithData(suite.T(), apiNonMeshServiceEndpointsData).Write(suite.T(), suite.client) + suite.api1Service = resourcetest.ResourceID(suite.api1Service.Id). + WithData(suite.T(), apiNonMeshServiceData). + Write(suite.T(), suite.client) destinationNonMeshServiceEndpoints := intermediate.CombinedDestinationRef{ - ServiceRef: resource.Reference(apiNonMeshServiceEndpoints.Owner, ""), + ServiceRef: api1ServiceRef, Port: "tcp", ExplicitDestinationsID: suite.webDestinations.Id, SourceProxies: map[resource.ReferenceKey]struct{}{ @@ -443,6 +528,7 @@ func (suite *dataFetcherSuite) TestFetcher_FetchExplicitDestinationsData() { }, } c.WriteDestination(destinationNonMeshServiceEndpoints) + suite.syncDestinations(destinationNonMeshServiceEndpoints) destinationRefs := []intermediate.CombinedDestinationRef{destinationNonMeshServiceEndpoints} destinations, statuses, err := f.FetchExplicitDestinationsData(suite.ctx, destinationRefs) @@ -452,89 +538,150 @@ func (suite *dataFetcherSuite) TestFetcher_FetchExplicitDestinationsData() { destinationRef := resource.IDToString(destinationNonMeshServiceEndpoints.ExplicitDestinationsID) serviceRef := resource.ReferenceToString(destinationNonMeshServiceEndpoints.ServiceRef) - require.Len(t, statuses[destinationRef].Conditions, 2) - prototest.AssertElementsMatch(t, statuses[destinationRef].Conditions, - []*pbresource.Condition{ - meshStatus.ConditionDestinationServiceFound(serviceRef), - meshStatus.ConditionMeshProtocolNotFound(serviceRef), - }) + destStatus, exists := statuses[destinationRef] + require.True(t, exists, "status map does not contain service: %s", destinationRef) + + prototest.AssertElementsMatch(t, []*pbresource.Condition{ + meshStatus.ConditionDestinationServiceFound(serviceRef), + meshStatus.ConditionMeshProtocolNotFound(serviceRef), + }, destStatus.Conditions) _, foundDest := c.ReadDestination(destinationNonMeshServiceEndpoints.ServiceRef, destinationNonMeshServiceEndpoints.Port) require.True(t, foundDest) - }) - suite.T().Run("invalid destinations: destination is not on the mesh", func(t *testing.T) { - // Update api1 to no longer be on the mesh. - suite.api1ServiceEndpoints = resourcetest.Resource(catalog.ServiceEndpointsType, "api-1"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - Addresses: []*pbcatalog.WorkloadAddress{{Host: "10.0.0.1"}}, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - }, - Identity: "api-1-identity", - }, - }, - }).Write(suite.T(), suite.client) + // Update the service to be mesh enabled again and check that the status is now valid. + suite.api1Service = resourcetest.ResourceID(suite.api1Service.Id). + WithData(suite.T(), suite.api1ServiceData). + Write(suite.T(), suite.client) - destinationRefs := []intermediate.CombinedDestinationRef{destination1} + destinations, statuses, err = f.FetchExplicitDestinationsData(suite.ctx, destinationRefs) + require.NoError(t, err) + require.Nil(t, destinations) + + destStatus, exists = statuses[destinationRef] + require.True(t, exists, "status map does not contain service: %s", destinationRef) + + prototest.AssertElementsMatch(t, []*pbresource.Condition{ + meshStatus.ConditionDestinationServiceFound(serviceRef), + meshStatus.ConditionMeshProtocolFound(serviceRef), + meshStatus.ConditionNonMeshProtocolDestinationPort(serviceRef, destinationNonMeshServiceEndpoints.Port), + meshStatus.ConditionDestinationComputedRoutesNotFound(serviceRef), + }, destStatus.Conditions) + }) + + testutil.RunStep(suite.T(), "invalid destinations: destination is pointing to a mesh port", func(t *testing.T) { + // Create a destination pointing to the mesh port. + destinationMeshDestinationPort := intermediate.CombinedDestinationRef{ + ServiceRef: api1ServiceRef, + Port: "mesh", + ExplicitDestinationsID: suite.webDestinations.Id, + SourceProxies: map[resource.ReferenceKey]struct{}{ + resource.NewReferenceKey(suite.webProxy.Id): {}, + }, + } + c.WriteDestination(destinationMeshDestinationPort) + suite.syncDestinations(destinationMeshDestinationPort) + destinationRefs := []intermediate.CombinedDestinationRef{destinationMeshDestinationPort} destinations, statuses, err := f.FetchExplicitDestinationsData(suite.ctx, destinationRefs) - serviceRef := resource.ReferenceToString(destination1.ServiceRef) - destinationRef := resource.IDToString(destination1.ExplicitDestinationsID) + serviceRef := resource.ReferenceToString(destinationMeshDestinationPort.ServiceRef) + destinationRef := resource.IDToString(destinationMeshDestinationPort.ExplicitDestinationsID) expectedStatus := &intermediate.Status{ ID: suite.webDestinations.Id, Generation: suite.webDestinations.Generation, Conditions: []*pbresource.Condition{ meshStatus.ConditionDestinationServiceFound(serviceRef), - meshStatus.ConditionMeshProtocolNotFound(serviceRef), + meshStatus.ConditionMeshProtocolFound(serviceRef), + meshStatus.ConditionMeshProtocolDestinationPort(serviceRef, destinationMeshDestinationPort.Port), }, } require.NoError(t, err) + destStatus, exists := statuses[destinationRef] + require.True(t, exists, "status map does not contain service: %s", destinationRef) + // Check that the status is generated correctly. - prototest.AssertDeepEqual(t, expectedStatus, statuses[destinationRef]) + prototest.AssertDeepEqual(t, expectedStatus, destStatus) // Check that we didn't return any destinations. - require.Nil(t, destinations) + require.Empty(t, destinations) // Check that destination service is still in cache because it's still referenced from the pbmesh.Upstreams // resource. - _, foundDest := c.ReadDestination(destination1.ServiceRef, destination1.Port) + _, foundDest := c.ReadDestination(destinationMeshDestinationPort.ServiceRef, destinationMeshDestinationPort.Port) require.True(t, foundDest) - // Update the endpoints to be mesh enabled again and check that the status is now valid. - suite.api1ServiceEndpoints = resourcetest.Resource(catalog.ServiceEndpointsType, "api-1"). - WithData(suite.T(), suite.api1ServiceEndpointsData).Write(suite.T(), suite.client) + // Update the destination to point to a non-mesh port and check that the status is now updated. + destinationRefs[0].Port = "tcp" + c.WriteDestination(destinationMeshDestinationPort) + suite.syncDestinations(destinationMeshDestinationPort) expectedStatus = &intermediate.Status{ ID: suite.webDestinations.Id, Generation: suite.webDestinations.Generation, Conditions: []*pbresource.Condition{ meshStatus.ConditionDestinationServiceFound(serviceRef), meshStatus.ConditionMeshProtocolFound(serviceRef), - meshStatus.ConditionNonMeshProtocolDestinationPort(serviceRef, destination1.Port), + meshStatus.ConditionNonMeshProtocolDestinationPort(serviceRef, destinationRefs[0].Port), + meshStatus.ConditionDestinationComputedRoutesNotFound(serviceRef), }, } _, statuses, err = f.FetchExplicitDestinationsData(suite.ctx, destinationRefs) require.NoError(t, err) - prototest.AssertDeepEqual(t, expectedStatus, statuses[destinationRef]) + + destStatus, exists = statuses[destinationRef] + require.True(t, exists, "status map does not contain service: %s", destinationRef) + + prototest.AssertDeepEqual(t, expectedStatus, destStatus) }) - suite.T().Run("invalid destinations: destination is pointing to a mesh port", func(t *testing.T) { - // Create a destination pointing to the mesh port. - destinationMeshDestinationPort := intermediate.CombinedDestinationRef{ - ServiceRef: resource.Reference(suite.api1Service.Id, ""), - Port: "mesh", - ExplicitDestinationsID: suite.webDestinations.Id, - SourceProxies: map[resource.ReferenceKey]struct{}{ - resource.NewReferenceKey(suite.webProxy.Id): {}, + destination1 := intermediate.CombinedDestinationRef{ + ServiceRef: resource.Reference(suite.api1Service.Id, ""), + Port: "tcp", + ExplicitDestinationsID: suite.webDestinations.Id, + SourceProxies: map[resource.ReferenceKey]struct{}{ + resource.NewReferenceKey(suite.webProxy.Id): {}, + }, + } + destination2 := intermediate.CombinedDestinationRef{ + ServiceRef: resource.Reference(suite.api2Service.Id, ""), + Port: "tcp1", + ExplicitDestinationsID: suite.webDestinations.Id, + SourceProxies: map[resource.ReferenceKey]struct{}{ + resource.NewReferenceKey(suite.webProxy.Id): {}, + }, + } + destination3 := intermediate.CombinedDestinationRef{ + ServiceRef: resource.Reference(suite.api2Service.Id, ""), + Port: "tcp2", + ExplicitDestinationsID: suite.webDestinations.Id, + SourceProxies: map[resource.ReferenceKey]struct{}{ + resource.NewReferenceKey(suite.webProxy.Id): {}, + }, + } + + testutil.RunStep(suite.T(), "invalid destinations: destination is pointing to a port but computed routes is not aware of it yet", func(t *testing.T) { + apiNonTCPServiceData := &pbcatalog.Service{ + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, }, } - c.WriteDestination(destinationMeshDestinationPort) - destinationRefs := []intermediate.CombinedDestinationRef{destinationMeshDestinationPort} + apiNonTCPService := resourcetest.ResourceID(suite.api1Service.Id). + WithData(suite.T(), apiNonTCPServiceData). + Build() + + api1ComputedRoutesID := resource.ReplaceType(types.ComputedRoutesType, suite.api1Service.Id) + api1ComputedRoutes := routestest.ReconcileComputedRoutes(suite.T(), suite.client, api1ComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](suite.T(), apiNonTCPService), + ) + require.NotNil(suite.T(), api1ComputedRoutes) + + // This destination points to TCP, but the computed routes is stale and only knows about HTTP. + writeDestination(t, destination1) + suite.syncDestinations(destination1) + destinationRefs := []intermediate.CombinedDestinationRef{destination1} destinations, statuses, err := f.FetchExplicitDestinationsData(suite.ctx, destinationRefs) serviceRef := resource.ReferenceToString(destination1.ServiceRef) @@ -545,82 +692,132 @@ func (suite *dataFetcherSuite) TestFetcher_FetchExplicitDestinationsData() { Conditions: []*pbresource.Condition{ meshStatus.ConditionDestinationServiceFound(serviceRef), meshStatus.ConditionMeshProtocolFound(serviceRef), - meshStatus.ConditionMeshProtocolDestinationPort(serviceRef, destinationMeshDestinationPort.Port), + meshStatus.ConditionNonMeshProtocolDestinationPort(serviceRef, destination1.Port), + meshStatus.ConditionDestinationComputedRoutesFound(serviceRef), + meshStatus.ConditionDestinationComputedRoutesPortNotFound(serviceRef, destination1.Port), }, } require.NoError(t, err) + destStatus, exists := statuses[destinationRef] + require.True(t, exists, "status map does not contain service: %s", destinationRef) + // Check that the status is generated correctly. - prototest.AssertDeepEqual(t, expectedStatus, statuses[destinationRef]) + prototest.AssertDeepEqual(t, expectedStatus, destStatus) // Check that we didn't return any destinations. require.Nil(t, destinations) // Check that destination service is still in cache because it's still referenced from the pbmesh.Upstreams // resource. - _, foundDest := c.ReadDestination(destinationMeshDestinationPort.ServiceRef, destinationMeshDestinationPort.Port) + _, foundDest := c.ReadDestination(destination1.ServiceRef, destination1.Port) require.True(t, foundDest) - // Update the destination to point to a non-mesh port and check that the status is now updated. - destinationRefs[0].Port = "tcp" - c.WriteDestination(destinationMeshDestinationPort) + // Update the computed routes not not lag. + api1ComputedRoutes = routestest.ReconcileComputedRoutes(suite.T(), suite.client, api1ComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api1Service), + ) + require.NotNil(suite.T(), api1ComputedRoutes) + expectedStatus = &intermediate.Status{ ID: suite.webDestinations.Id, Generation: suite.webDestinations.Generation, Conditions: []*pbresource.Condition{ meshStatus.ConditionDestinationServiceFound(serviceRef), meshStatus.ConditionMeshProtocolFound(serviceRef), - meshStatus.ConditionNonMeshProtocolDestinationPort(serviceRef, destinationRefs[0].Port), + meshStatus.ConditionNonMeshProtocolDestinationPort(serviceRef, destination1.Port), + meshStatus.ConditionDestinationComputedRoutesFound(serviceRef), + meshStatus.ConditionDestinationComputedRoutesPortFound(serviceRef, destination1.Port), }, } - _, statuses, err = f.FetchExplicitDestinationsData(suite.ctx, destinationRefs) + actualDestinations, statuses, err := f.FetchExplicitDestinationsData(suite.ctx, destinationRefs) require.NoError(t, err) - prototest.AssertDeepEqual(t, expectedStatus, statuses[destinationRef]) + + destStatus, exists = statuses[destinationRef] + require.True(t, exists, "status map does not contain service: %s", destinationRef) + + prototest.AssertDeepEqual(t, expectedStatus, destStatus) + + expectedDestinations := []*intermediate.Destination{ + { + Explicit: suite.webDestinationsData.Upstreams[0], + Service: resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api1Service), + ComputedPortRoutes: routestest.MutateTarget(suite.T(), api1ComputedRoutes.Data.PortedConfigs["tcp"], suite.api1Service.Id, "tcp", func(details *pbmesh.BackendTargetDetails) { + se := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](suite.T(), suite.api1ServiceEndpoints) + details.ServiceEndpointsId = se.Resource.Id + details.ServiceEndpoints = se.Data + details.IdentityRefs = []*pbresource.Reference{{ + Name: "api-1-identity", + Tenancy: suite.api1Service.Id.Tenancy, + }} + }), + }, + } + prototest.AssertElementsMatch(t, expectedDestinations, actualDestinations) }) - suite.T().Run("happy path", func(t *testing.T) { + testutil.RunStep(suite.T(), "happy path", func(t *testing.T) { + writeDestination(t, destination1) + writeDestination(t, destination2) + writeDestination(t, destination3) + suite.syncDestinations(destination1, destination2, destination3) + + // Write a default ComputedRoutes for api1 and api2. + var ( + api1ComputedRoutesID = resource.ReplaceType(types.ComputedRoutesType, suite.api1Service.Id) + api2ComputedRoutesID = resource.ReplaceType(types.ComputedRoutesType, suite.api2Service.Id) + ) + api1ComputedRoutes := routestest.ReconcileComputedRoutes(suite.T(), suite.client, api1ComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api1Service), + ) + require.NotNil(suite.T(), api1ComputedRoutes) + api2ComputedRoutes := routestest.ReconcileComputedRoutes(suite.T(), suite.client, api2ComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api2Service), + ) + require.NotNil(suite.T(), api2ComputedRoutes) + destinationRefs := []intermediate.CombinedDestinationRef{destination1, destination2, destination3} expectedDestinations := []*intermediate.Destination{ { Explicit: suite.webDestinationsData.Upstreams[0], - ServiceEndpoints: &intermediate.ServiceEndpoints{ - Resource: suite.api1ServiceEndpoints, - Endpoints: suite.api1ServiceEndpointsData, - }, - Identities: []*pbresource.Reference{ - { + Service: resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api1Service), + ComputedPortRoutes: routestest.MutateTarget(suite.T(), api1ComputedRoutes.Data.PortedConfigs["tcp"], suite.api1Service.Id, "tcp", func(details *pbmesh.BackendTargetDetails) { + se := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](suite.T(), suite.api1ServiceEndpoints) + details.ServiceEndpointsId = se.Resource.Id + details.ServiceEndpoints = se.Data + details.IdentityRefs = []*pbresource.Reference{{ Name: "api-1-identity", Tenancy: suite.api1Service.Id.Tenancy, - }, - }, + }} + }), }, { Explicit: suite.webDestinationsData.Upstreams[1], - ServiceEndpoints: &intermediate.ServiceEndpoints{ - Resource: suite.api2ServiceEndpoints, - Endpoints: suite.api2ServiceEndpointsData, - }, - Identities: []*pbresource.Reference{ - { + Service: resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api2Service), + ComputedPortRoutes: routestest.MutateTarget(suite.T(), api2ComputedRoutes.Data.PortedConfigs["tcp1"], suite.api2Service.Id, "tcp1", func(details *pbmesh.BackendTargetDetails) { + se := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](suite.T(), suite.api2ServiceEndpoints) + details.ServiceEndpointsId = se.Resource.Id + details.ServiceEndpoints = se.Data + details.IdentityRefs = []*pbresource.Reference{{ Name: "api-2-identity", Tenancy: suite.api2Service.Id.Tenancy, - }, - }, + }} + }), }, { Explicit: suite.webDestinationsData.Upstreams[2], - ServiceEndpoints: &intermediate.ServiceEndpoints{ - Resource: suite.api2ServiceEndpoints, - Endpoints: suite.api2ServiceEndpointsData, - }, - Identities: []*pbresource.Reference{ - { + Service: resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api2Service), + ComputedPortRoutes: routestest.MutateTarget(suite.T(), api2ComputedRoutes.Data.PortedConfigs["tcp2"], suite.api2Service.Id, "tcp2", func(details *pbmesh.BackendTargetDetails) { + se := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](suite.T(), suite.api2ServiceEndpoints) + details.ServiceEndpointsId = se.Resource.Id + details.ServiceEndpoints = se.Data + details.IdentityRefs = []*pbresource.Reference{{ Name: "api-2-identity", Tenancy: suite.api2Service.Id.Tenancy, - }, - }, + }} + }), }, } var expectedConditions []*pbresource.Condition @@ -629,7 +826,10 @@ func (suite *dataFetcherSuite) TestFetcher_FetchExplicitDestinationsData() { expectedConditions = append(expectedConditions, meshStatus.ConditionDestinationServiceFound(ref), meshStatus.ConditionMeshProtocolFound(ref), - meshStatus.ConditionNonMeshProtocolDestinationPort(ref, d.Port)) + meshStatus.ConditionNonMeshProtocolDestinationPort(ref, d.Port), + meshStatus.ConditionDestinationComputedRoutesFound(ref), + meshStatus.ConditionDestinationComputedRoutesPortFound(ref, d.Port), + ) } actualDestinations, statuses, err := f.FetchExplicitDestinationsData(suite.ctx, destinationRefs) @@ -645,52 +845,14 @@ func (suite *dataFetcherSuite) TestFetcher_FetchExplicitDestinationsData() { } func (suite *dataFetcherSuite) TestFetcher_FetchImplicitDestinationsData() { - existingDestinations := []*intermediate.Destination{ - { - Explicit: suite.webDestinationsData.Upstreams[0], - ServiceEndpoints: &intermediate.ServiceEndpoints{ - Resource: suite.api1ServiceEndpoints, - Endpoints: suite.api1ServiceEndpointsData, - }, - Identities: []*pbresource.Reference{ - { - Name: "api-1-identity", - Tenancy: suite.api1Service.Id.Tenancy, - }, - }, - }, - { - Explicit: suite.webDestinationsData.Upstreams[1], - ServiceEndpoints: &intermediate.ServiceEndpoints{ - Resource: suite.api2ServiceEndpoints, - Endpoints: suite.api2ServiceEndpointsData, - }, - Identities: []*pbresource.Reference{ - { - Name: "api-2-identity", - Tenancy: suite.api2Service.Id.Tenancy, - }, - }, - }, - { - Explicit: suite.webDestinationsData.Upstreams[2], - ServiceEndpoints: &intermediate.ServiceEndpoints{ - Resource: suite.api2ServiceEndpoints, - Endpoints: suite.api2ServiceEndpointsData, - }, - Identities: []*pbresource.Reference{ - { - Name: "api-2-identity", - Tenancy: suite.api2Service.Id.Tenancy, - }, - }, - }, - } - // Create a few other services to be implicit upstreams. api3Service := resourcetest.Resource(catalog.ServiceType, "api-3"). WithData(suite.T(), &pbcatalog.Service{ VirtualIps: []string{"192.1.1.1"}, + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "tcp", VirtualPort: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, + {TargetPort: "mesh", VirtualPort: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, }). Write(suite.T(), suite.client) @@ -712,30 +874,92 @@ func (suite *dataFetcherSuite) TestFetcher_FetchImplicitDestinationsData() { }, } api3ServiceEndpoints := resourcetest.Resource(catalog.ServiceEndpointsType, "api-3"). - WithData(suite.T(), api3ServiceEndpointsData).Write(suite.T(), suite.client) + WithData(suite.T(), api3ServiceEndpointsData). + Write(suite.T(), suite.client) - f := Fetcher{ - Client: suite.client, - } + // Write a default ComputedRoutes for api1, api2, and api3. + var ( + api1ComputedRoutesID = resource.ReplaceType(types.ComputedRoutesType, suite.api1Service.Id) + api2ComputedRoutesID = resource.ReplaceType(types.ComputedRoutesType, suite.api2Service.Id) + api3ComputedRoutesID = resource.ReplaceType(types.ComputedRoutesType, api3Service.Id) + ) + api1ComputedRoutes := routestest.ReconcileComputedRoutes(suite.T(), suite.client, api1ComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api1Service), + ) + require.NotNil(suite.T(), api1ComputedRoutes) + api2ComputedRoutes := routestest.ReconcileComputedRoutes(suite.T(), suite.client, api2ComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api2Service), + ) + require.NotNil(suite.T(), api2ComputedRoutes) + api3ComputedRoutes := routestest.ReconcileComputedRoutes(suite.T(), suite.client, api3ComputedRoutesID, + resourcetest.MustDecode[*pbcatalog.Service](suite.T(), api3Service), + ) + require.NotNil(suite.T(), api3ComputedRoutes) - expDestinations := append(existingDestinations, &intermediate.Destination{ - ServiceEndpoints: &intermediate.ServiceEndpoints{ - Resource: api3ServiceEndpoints, - Endpoints: api3ServiceEndpointsData, + existingDestinations := []*intermediate.Destination{ + { + Explicit: suite.webDestinationsData.Upstreams[0], + Service: resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api1Service), + ComputedPortRoutes: routestest.MutateTarget(suite.T(), api1ComputedRoutes.Data.PortedConfigs["tcp"], suite.api1Service.Id, "tcp", func(details *pbmesh.BackendTargetDetails) { + se := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](suite.T(), suite.api1ServiceEndpoints) + details.ServiceEndpointsId = se.Resource.Id + details.ServiceEndpoints = se.Data + details.IdentityRefs = []*pbresource.Reference{{ + Name: "api-1-identity", + Tenancy: suite.api1Service.Id.Tenancy, + }} + }), }, - Identities: []*pbresource.Reference{ - { - Name: "api-3-identity", - Tenancy: api3Service.Id.Tenancy, - }, + { + Explicit: suite.webDestinationsData.Upstreams[1], + Service: resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api2Service), + ComputedPortRoutes: routestest.MutateTarget(suite.T(), api2ComputedRoutes.Data.PortedConfigs["tcp1"], suite.api2Service.Id, "tcp1", func(details *pbmesh.BackendTargetDetails) { + se := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](suite.T(), suite.api2ServiceEndpoints) + details.ServiceEndpointsId = se.Resource.Id + details.ServiceEndpoints = se.Data + details.IdentityRefs = []*pbresource.Reference{{ + Name: "api-2-identity", + Tenancy: suite.api2Service.Id.Tenancy, + }} + }), }, - VirtualIPs: []string{"192.1.1.1"}, - }) + { + Explicit: suite.webDestinationsData.Upstreams[2], + Service: resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api2Service), + ComputedPortRoutes: routestest.MutateTarget(suite.T(), api2ComputedRoutes.Data.PortedConfigs["tcp2"], suite.api2Service.Id, "tcp2", func(details *pbmesh.BackendTargetDetails) { + se := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](suite.T(), suite.api2ServiceEndpoints) + details.ServiceEndpointsId = se.Resource.Id + details.ServiceEndpoints = se.Data + details.IdentityRefs = []*pbresource.Reference{{ + Name: "api-2-identity", + Tenancy: suite.api2Service.Id.Tenancy, + }} + }), + }, + { + // implicit + Service: resourcetest.MustDecode[*pbcatalog.Service](suite.T(), api3Service), + ComputedPortRoutes: routestest.MutateTarget(suite.T(), api3ComputedRoutes.Data.PortedConfigs["tcp"], api3Service.Id, "tcp", func(details *pbmesh.BackendTargetDetails) { + se := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](suite.T(), api3ServiceEndpoints) + details.ServiceEndpointsId = se.Resource.Id + details.ServiceEndpoints = se.Data + details.IdentityRefs = []*pbresource.Reference{{ + Name: "api-3-identity", + Tenancy: api3Service.Id.Tenancy, + }} + }), + VirtualIPs: []string{"192.1.1.1"}, + }, + } + + f := Fetcher{ + Client: suite.client, + } actualDestinations, err := f.FetchImplicitDestinationsData(context.Background(), suite.webProxy.Id, existingDestinations) require.NoError(suite.T(), err) - prototest.AssertElementsMatch(suite.T(), expDestinations, actualDestinations) + prototest.AssertElementsMatch(suite.T(), existingDestinations, actualDestinations) } func (suite *dataFetcherSuite) TestFetcher_FetchAndMergeProxyConfigurations() { diff --git a/internal/mesh/internal/controllers/sidecarproxy/status/status.go b/internal/mesh/internal/controllers/sidecarproxy/status/status.go index d97fc5c64b5c..04a315e14897 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/status/status.go +++ b/internal/mesh/internal/controllers/sidecarproxy/status/status.go @@ -20,6 +20,12 @@ const ( StatusReasonDestinationServiceNotFound = "ServiceNotFound" StatusReasonDestinationServiceFound = "ServiceFound" + + StatusReasonDestinationComputedRoutesNotFound = "ComputedRoutesNotFound" + StatusReasonDestinationComputedRoutesFound = "ComputedRoutesFound" + + StatusReasonDestinationComputedRoutesPortNotFound = "ComputedRoutesPortNotFound" + StatusReasonDestinationComputedRoutesPortFound = "ComputedRoutesPortFound" ) func ConditionMeshProtocolNotFound(serviceRef string) *pbresource.Condition { @@ -75,3 +81,39 @@ func ConditionNonMeshProtocolDestinationPort(serviceRef, port string) *pbresourc Message: fmt.Sprintf("destination port %q for service %q has a non-mesh protocol", port, serviceRef), } } + +func ConditionDestinationComputedRoutesNotFound(serviceRef string) *pbresource.Condition { + return &pbresource.Condition{ + Type: StatusConditionDestinationAccepted, + State: pbresource.Condition_STATE_FALSE, + Reason: StatusReasonDestinationComputedRoutesNotFound, + Message: fmt.Sprintf("computed routes %q does not exist.", serviceRef), + } +} + +func ConditionDestinationComputedRoutesFound(serviceRef string) *pbresource.Condition { + return &pbresource.Condition{ + Type: StatusConditionDestinationAccepted, + State: pbresource.Condition_STATE_TRUE, + Reason: StatusReasonDestinationComputedRoutesNotFound, + Message: fmt.Sprintf("computed routes %q exists.", serviceRef), + } +} + +func ConditionDestinationComputedRoutesPortNotFound(serviceRef, port string) *pbresource.Condition { + return &pbresource.Condition{ + Type: StatusConditionDestinationAccepted, + State: pbresource.Condition_STATE_FALSE, + Reason: StatusReasonDestinationComputedRoutesPortNotFound, + Message: fmt.Sprintf("computed routes %q does not exist for port %q.", serviceRef, port), + } +} + +func ConditionDestinationComputedRoutesPortFound(serviceRef, port string) *pbresource.Condition { + return &pbresource.Condition{ + Type: StatusConditionDestinationAccepted, + State: pbresource.Condition_STATE_TRUE, + Reason: StatusReasonDestinationComputedRoutesPortNotFound, + Message: fmt.Sprintf("computed routes %q exists for port %q.", serviceRef, port), + } +} diff --git a/internal/mesh/internal/mappers/sidecarproxymapper/computed_routes_mapper.go b/internal/mesh/internal/mappers/sidecarproxymapper/computed_routes_mapper.go new file mode 100644 index 000000000000..de97043d4ff0 --- /dev/null +++ b/internal/mesh/internal/mappers/sidecarproxymapper/computed_routes_mapper.go @@ -0,0 +1,44 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package sidecarproxymapper + +import ( + "context" + + "github.com/hashicorp/consul/internal/catalog" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/mesh/internal/types" + "github.com/hashicorp/consul/internal/resource" + pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +func (m *Mapper) MapComputedRoutesToProxyStateTemplate(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + computedRoutes, err := resource.Decode[*pbmesh.ComputedRoutes](res) + if err != nil { + return nil, err + } + + reqs, err := m.mapComputedRoutesToProxyStateTemplate(ctx, rt, res.Id) + if err != nil { + return nil, err + } + + m.computedRoutesCache.TrackComputedRoutes(computedRoutes) + + return reqs, nil +} + +func (m *Mapper) mapComputedRoutesToProxyStateTemplate(ctx context.Context, rt controller.Runtime, computedRoutesID *pbresource.ID) ([]controller.Request, error) { + // Each Destination gets a single ComputedRoutes. + serviceID := resource.ReplaceType(catalog.ServiceType, computedRoutesID) + serviceRef := resource.Reference(serviceID, "") + + ids, err := m.mapServiceThroughDestinationsToProxyStateTemplates(ctx, rt, serviceRef) + if err != nil { + return nil, err + } + + return controller.MakeRequests(types.ProxyStateTemplateType, ids), nil +} diff --git a/internal/mesh/internal/mappers/sidecarproxymapper/destinations_mapper.go b/internal/mesh/internal/mappers/sidecarproxymapper/destinations_mapper.go index 0fb14eb48645..5dd30b155553 100644 --- a/internal/mesh/internal/mappers/sidecarproxymapper/destinations_mapper.go +++ b/internal/mesh/internal/mappers/sidecarproxymapper/destinations_mapper.go @@ -14,8 +14,7 @@ import ( ) func (m *Mapper) MapDestinationsToProxyStateTemplate(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - var destinations pbmesh.Upstreams - err := res.Data.UnmarshalTo(&destinations) + destinations, err := resource.Decode[*pbmesh.Upstreams](res) if err != nil { return nil, err } @@ -23,7 +22,7 @@ func (m *Mapper) MapDestinationsToProxyStateTemplate(ctx context.Context, rt con // Look up workloads for this destinations. sourceProxyIDs := make(map[resource.ReferenceKey]struct{}) - requests, err := mapSelectorToProxyStateTemplates(ctx, rt.Client, destinations.Workloads, res.Id.Tenancy, func(id *pbresource.ID) { + requests, err := mapSelectorToProxyStateTemplates(ctx, rt.Client, destinations.Data.Workloads, res.Id.Tenancy, func(id *pbresource.ID) { sourceProxyIDs[resource.NewReferenceKey(id)] = struct{}{} }) if err != nil { @@ -31,7 +30,7 @@ func (m *Mapper) MapDestinationsToProxyStateTemplate(ctx context.Context, rt con } // Add this destination to destinationsCache. - for _, destination := range destinations.Upstreams { + for _, destination := range destinations.Data.Upstreams { destinationRef := intermediate.CombinedDestinationRef{ ServiceRef: destination.DestinationRef, Port: destination.DestinationPort, diff --git a/internal/mesh/internal/mappers/sidecarproxymapper/mapper.go b/internal/mesh/internal/mappers/sidecarproxymapper/mapper.go index 440f6fd72fe6..1faf74ebb94a 100644 --- a/internal/mesh/internal/mappers/sidecarproxymapper/mapper.go +++ b/internal/mesh/internal/mappers/sidecarproxymapper/mapper.go @@ -16,14 +16,20 @@ import ( ) type Mapper struct { - destinationsCache *sidecarproxycache.DestinationsCache - proxyCfgCache *sidecarproxycache.ProxyConfigurationCache + destinationsCache *sidecarproxycache.DestinationsCache + proxyCfgCache *sidecarproxycache.ProxyConfigurationCache + computedRoutesCache *sidecarproxycache.ComputedRoutesCache } -func New(destinationsCache *sidecarproxycache.DestinationsCache, proxyCfgCache *sidecarproxycache.ProxyConfigurationCache) *Mapper { +func New( + destinationsCache *sidecarproxycache.DestinationsCache, + proxyCfgCache *sidecarproxycache.ProxyConfigurationCache, + computedRoutesCache *sidecarproxycache.ComputedRoutesCache, +) *Mapper { return &Mapper{ - destinationsCache: destinationsCache, - proxyCfgCache: proxyCfgCache, + destinationsCache: destinationsCache, + proxyCfgCache: proxyCfgCache, + computedRoutesCache: computedRoutesCache, } } diff --git a/internal/mesh/internal/mappers/sidecarproxymapper/service_endpoints_mapper.go b/internal/mesh/internal/mappers/sidecarproxymapper/service_endpoints_mapper.go index 821743d4b0c2..641ca1e4b389 100644 --- a/internal/mesh/internal/mappers/sidecarproxymapper/service_endpoints_mapper.go +++ b/internal/mesh/internal/mappers/sidecarproxymapper/service_endpoints_mapper.go @@ -10,7 +10,6 @@ import ( "github.com/hashicorp/consul/internal/controller" "github.com/hashicorp/consul/internal/mesh/internal/types" "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/storage" pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" "github.com/hashicorp/consul/proto-public/pbresource" ) @@ -18,18 +17,26 @@ import ( // MapServiceEndpointsToProxyStateTemplate maps catalog.ServiceEndpoints objects to the IDs of // ProxyStateTemplate. func (m *Mapper) MapServiceEndpointsToProxyStateTemplate(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - // This mapper needs to look up workload IDs from service endpoints and replace them with ProxyStateTemplate type. - var serviceEndpoints pbcatalog.ServiceEndpoints - err := res.Data.UnmarshalTo(&serviceEndpoints) + // This mapper has two jobs: + // + // 1. It needs to look up workload IDs from service endpoints and replace + // them with ProxyStateTemplate type. We do this so we don't need to watch + // Workloads to discover them, since ProxyStateTemplates are name-aligned + // with Workloads. + // + // 2. It needs to find any PST that needs to DISCOVER endpoints for this + // service as a part of mesh configuration and traffic routing. + + serviceEndpoints, err := resource.Decode[*pbcatalog.ServiceEndpoints](res) if err != nil { return nil, err } var result []controller.Request - // First, we need to generate requests from workloads this "endpoints" points to - // so that we can re-generate proxy state for the sidecar proxy. - for _, endpoint := range serviceEndpoints.Endpoints { + // (1) First, we need to generate requests from workloads this "endpoints" + // points to so that we can re-generate proxy state for the sidecar proxy. + for _, endpoint := range serviceEndpoints.Data.Endpoints { // Convert the reference to a workload to a ProxyStateTemplate ID. // Because these resources are name and tenancy aligned, we only need to change the type. @@ -37,56 +44,29 @@ func (m *Mapper) MapServiceEndpointsToProxyStateTemplate(ctx context.Context, rt // services external to Consul, and we don't need to reconcile those as they don't have // associated workloads. if endpoint.TargetRef != nil { - id := &pbresource.ID{ - Name: endpoint.TargetRef.Name, - Tenancy: endpoint.TargetRef.Tenancy, - Type: types.ProxyStateTemplateType, - } result = append(result, controller.Request{ - ID: id, + ID: resource.ReplaceType(types.ProxyStateTemplateType, endpoint.TargetRef), }) } } - // Look up any source proxies for this service and generate updates. - serviceID := resource.ReplaceType(catalog.ServiceType, res.Id) + // (2) Now walk the mesh configuration information backwards. + + // ServiceEndpoints -> Service + targetServiceRef := resource.ReplaceType(catalog.ServiceType, res.Id) - // Second, we need to generate requests for any proxies where this service is a destination. - if len(serviceEndpoints.Endpoints) > 0 { - // All port names in the endpoints object should be the same as we filter out to ports that are selected - // by the service, and so it's sufficient to check just the first endpoint. - for portName, port := range serviceEndpoints.Endpoints[0].Ports { - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - // Skip mesh ports. These should never be used as destination ports. - continue - } - serviceRef := resource.Reference(serviceID, "") - if destination, ok := m.destinationsCache.ReadDestination(serviceRef, portName); ok { - for refKey := range destination.SourceProxies { - result = append(result, controller.Request{ID: refKey.ToID()}) - } - } + // Find all ComputedRoutes that reference this service. + routeIDs := m.computedRoutesCache.ComputedRoutesByService(targetServiceRef) + for _, routeID := range routeIDs { + // Find all Upstreams that reference a Service aligned with this ComputedRoutes. + // Afterwards, find all Workloads selected by the Upstreams, and align a PST with those. + reqs, err := m.mapComputedRoutesToProxyStateTemplate(ctx, rt, routeID) + if err != nil { + return nil, err } - } - // todo (ishustava): this is a stub for now until we implement implicit destinations. - // For tproxy, we generate requests for all proxy states in the cluster. - // This will generate duplicate events for proxies already added above, - // however, we expect that the controller runtime will de-dup for us. - rsp, err := rt.Client.List(ctx, &pbresource.ListRequest{ - Type: types.ProxyStateTemplateType, - Tenancy: &pbresource.Tenancy{ - Namespace: storage.Wildcard, - Partition: res.Id.Tenancy.Partition, - PeerName: res.Id.Tenancy.PeerName, - }, - }) - if err != nil { - return nil, err - } - for _, r := range rsp.Resources { - result = append(result, controller.Request{ID: r.Id}) + result = append(result, reqs...) } - return result, err + return result, nil } diff --git a/internal/mesh/internal/mappers/sidecarproxymapper/service_endpoints_mapper_test.go b/internal/mesh/internal/mappers/sidecarproxymapper/service_endpoints_mapper_test.go deleted file mode 100644 index 4ee0dfaa418f..000000000000 --- a/internal/mesh/internal/mappers/sidecarproxymapper/service_endpoints_mapper_test.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package sidecarproxymapper - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/cache/sidecarproxycache" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/mesh/internal/types/intermediate" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestMapServiceEndpointsToProxyStateTemplate(t *testing.T) { - client := svctest.RunResourceService(t, types.Register, catalog.RegisterTypes) - workload1 := resourcetest.Resource(catalog.WorkloadType, "workload-1"). - WithTenancy(resource.DefaultNamespacedTenancy()).Build() - workload2 := resourcetest.Resource(catalog.WorkloadType, "workload-2"). - WithTenancy(resource.DefaultNamespacedTenancy()).Build() - serviceEndpoints := resourcetest.Resource(catalog.ServiceEndpointsType, "service"). - WithData(t, &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: workload1.Id, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp1": {Port: 8080}, - "tcp2": {Port: 8081}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - { - TargetRef: workload2.Id, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp1": {Port: 8080}, - "tcp2": {Port: 8081}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Build() - proxyTmpl1ID := resourcetest.Resource(types.ProxyStateTemplateType, "workload-1"). - WithTenancy(resource.DefaultNamespacedTenancy()).ID() - proxyTmpl2ID := resourcetest.Resource(types.ProxyStateTemplateType, "workload-2"). - WithTenancy(resource.DefaultNamespacedTenancy()).ID() - - c := sidecarproxycache.NewDestinationsCache() - mapper := &Mapper{destinationsCache: c} - sourceProxy1 := resourcetest.Resource(types.ProxyStateTemplateType, "workload-3"). - WithTenancy(resource.DefaultNamespacedTenancy()).ID() - sourceProxy2 := resourcetest.Resource(types.ProxyStateTemplateType, "workload-4"). - WithTenancy(resource.DefaultNamespacedTenancy()).ID() - sourceProxy3 := resourcetest.Resource(types.ProxyStateTemplateType, "workload-5"). - WithTenancy(resource.DefaultNamespacedTenancy()).ID() - destination1 := intermediate.CombinedDestinationRef{ - ServiceRef: resourcetest.Resource(catalog.ServiceType, "service").ReferenceNoSection(), - Port: "tcp1", - SourceProxies: map[resource.ReferenceKey]struct{}{ - resource.NewReferenceKey(sourceProxy1): {}, - resource.NewReferenceKey(sourceProxy2): {}, - }, - } - destination2 := intermediate.CombinedDestinationRef{ - ServiceRef: resourcetest.Resource(catalog.ServiceType, "service").ReferenceNoSection(), - Port: "tcp2", - SourceProxies: map[resource.ReferenceKey]struct{}{ - resource.NewReferenceKey(sourceProxy1): {}, - resource.NewReferenceKey(sourceProxy3): {}, - }, - } - destination3 := intermediate.CombinedDestinationRef{ - ServiceRef: resourcetest.Resource(catalog.ServiceType, "service").ReferenceNoSection(), - Port: "mesh", - SourceProxies: map[resource.ReferenceKey]struct{}{ - resource.NewReferenceKey(sourceProxy1): {}, - resource.NewReferenceKey(sourceProxy3): {}, - }, - } - c.WriteDestination(destination1) - c.WriteDestination(destination2) - c.WriteDestination(destination3) - - expRequests := []controller.Request{ - {ID: proxyTmpl1ID}, - {ID: proxyTmpl2ID}, - {ID: sourceProxy1}, - {ID: sourceProxy2}, - {ID: sourceProxy1}, - {ID: sourceProxy3}, - } - - requests, err := mapper.MapServiceEndpointsToProxyStateTemplate(context.Background(), controller.Runtime{Client: client}, serviceEndpoints) - require.NoError(t, err) - prototest.AssertElementsMatch(t, expRequests, requests) -} diff --git a/internal/mesh/internal/mappers/sidecarproxymapper/service_mapper.go b/internal/mesh/internal/mappers/sidecarproxymapper/service_mapper.go new file mode 100644 index 000000000000..8cc37d426d6d --- /dev/null +++ b/internal/mesh/internal/mappers/sidecarproxymapper/service_mapper.go @@ -0,0 +1,95 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package sidecarproxymapper + +import ( + "context" + + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/mesh/internal/types" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/storage" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +func (m *Mapper) MapServiceToProxyStateTemplate(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + serviceRef := resource.Reference(res.Id, "") + + ids, err := m.mapServiceThroughDestinationsToProxyStateTemplates(ctx, rt, serviceRef) + if err != nil { + return nil, err + } + + return controller.MakeRequests(types.ProxyStateTemplateType, ids), nil +} + +// mapServiceThroughDestinationsToProxyStateTemplates takes and explicit +// Service and traverses back through Destinations to Workloads to +// ProxyStateTemplates. +// +// This is in a separate function so it can be chained for more complicated +// relationships. +func (m *Mapper) mapServiceThroughDestinationsToProxyStateTemplates( + ctx context.Context, + rt controller.Runtime, + serviceRef *pbresource.Reference, +) ([]*pbresource.ID, error) { + + // The relationship is: + // + // - PST (replace type) Workload + // - Workload (selected by) Upstreams + // - Upstream (contains) Service + // + // When we wake up for Service we should: + // + // - look for Service in all Destinations(upstreams) + // - follow selectors backwards to Workloads + // - rewrite types to PST + + var pstIDs []*pbresource.ID + + destinations := m.destinationsCache.ReadDestinationsByServiceAllPorts(serviceRef) + for _, destination := range destinations { + for refKey := range destination.SourceProxies { + pstIDs = append(pstIDs, refKey.ToID()) + } + } + + // TODO(v2): remove this after we can do proper performant implicit upstream determination + // + // TODO(rb): shouldn't this instead list all Workloads that have a mesh port? + allIDs, err := m.listAllProxyStateTemplatesTemporarily(ctx, rt, serviceRef.Tenancy) + if err != nil { + return nil, err + } + + pstIDs = append(pstIDs, allIDs...) + + return pstIDs, nil +} + +func (m *Mapper) listAllProxyStateTemplatesTemporarily(ctx context.Context, rt controller.Runtime, tenancy *pbresource.Tenancy) ([]*pbresource.ID, error) { + // todo (ishustava): this is a stub for now until we implement implicit destinations. + // For tproxy, we generate requests for all proxy states in the cluster. + // This will generate duplicate events for proxies already added above, + // however, we expect that the controller runtime will de-dup for us. + rsp, err := rt.Client.List(ctx, &pbresource.ListRequest{ + Type: types.ProxyStateTemplateType, + Tenancy: &pbresource.Tenancy{ + Namespace: storage.Wildcard, + Partition: tenancy.Partition, + PeerName: tenancy.PeerName, + }, + }) + if err != nil { + return nil, err + } + + result := make([]*pbresource.ID, 0, len(rsp.Resources)) + for _, r := range rsp.Resources { + result = append(result, r.Id) + } + return result, nil +} diff --git a/internal/mesh/internal/mappers/sidecarproxymapper/unified_mapper_test.go b/internal/mesh/internal/mappers/sidecarproxymapper/unified_mapper_test.go new file mode 100644 index 000000000000..e0a37a635815 --- /dev/null +++ b/internal/mesh/internal/mappers/sidecarproxymapper/unified_mapper_test.go @@ -0,0 +1,403 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package sidecarproxymapper + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" + "github.com/hashicorp/consul/internal/catalog" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/mesh/internal/cache/sidecarproxycache" + "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/routestest" + "github.com/hashicorp/consul/internal/mesh/internal/types" + "github.com/hashicorp/consul/internal/mesh/internal/types/intermediate" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/resource/resourcetest" + pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" + pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" +) + +func TestUnified_AllMappingsToProxyStateTemplate(t *testing.T) { + var ( + destCache = sidecarproxycache.NewDestinationsCache() + // proxyCfgCache = sidecarproxycache.NewProxyConfigurationCache() + routesCache = sidecarproxycache.NewComputedRoutesCache() + mapper = New(destCache, nil, routesCache) + + client = svctest.RunResourceService(t, types.Register, catalog.RegisterTypes) + ) + + anyServiceData := &pbcatalog.Service{ + Ports: []*pbcatalog.ServicePort{ + { + TargetPort: "tcp1", + Protocol: pbcatalog.Protocol_PROTOCOL_TCP, + }, + { + TargetPort: "tcp2", + Protocol: pbcatalog.Protocol_PROTOCOL_TCP, + }, + { + TargetPort: "mesh", + Protocol: pbcatalog.Protocol_PROTOCOL_MESH, + }, + }, + } + + anyWorkloadPorts := map[string]*pbcatalog.WorkloadPort{ + "tcp1": {Port: 8080}, + "tcp2": {Port: 8081}, + "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + } + + // The thing we link through Destinations. + destService := resourcetest.Resource(catalog.ServiceType, "web"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, anyServiceData). + Build() + destServiceRef := resource.Reference(destService.Id, "") + + // The thing we reach through the mesh config. + targetService := resourcetest.Resource(catalog.ServiceType, "db"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, anyServiceData). + Build() + targetServiceRef := resource.Reference(targetService.Id, "") + + backupTargetService := resourcetest.Resource(catalog.ServiceType, "db-backup"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, anyServiceData). + Build() + backupTargetServiceRef := resource.Reference(backupTargetService.Id, "") + + // The way we make 'web' actually route traffic to 'db'. + tcpRoute := resourcetest.Resource(types.TCPRouteType, "tcp-route"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, &pbmesh.TCPRoute{ + ParentRefs: []*pbmesh.ParentReference{{ + Ref: destServiceRef, + }}, + Rules: []*pbmesh.TCPRouteRule{{ + BackendRefs: []*pbmesh.TCPBackendRef{{ + BackendRef: &pbmesh.BackendReference{ + Ref: targetServiceRef, + }, + }}, + }}, + }). + Build() + failoverPolicy := resourcetest.ResourceID(resource.ReplaceType(catalog.FailoverPolicyType, targetService.Id)). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, &pbcatalog.FailoverPolicy{ + Config: &pbcatalog.FailoverConfig{ + Destinations: []*pbcatalog.FailoverDestination{{ + Ref: backupTargetServiceRef, + }}, + }, + }). + Build() + webRoutes := routestest.BuildComputedRoutes(t, resource.ReplaceType(types.ComputedRoutesType, destService.Id), + resourcetest.MustDecode[*pbcatalog.Service](t, destService), + resourcetest.MustDecode[*pbcatalog.Service](t, targetService), + resourcetest.MustDecode[*pbcatalog.Service](t, backupTargetService), + resourcetest.MustDecode[*pbmesh.TCPRoute](t, tcpRoute), + resourcetest.MustDecode[*pbcatalog.FailoverPolicy](t, failoverPolicy), + ) + + var ( + destWorkload1 = newID(catalog.WorkloadType, "dest-workload-1") + destWorkload2 = newID(catalog.WorkloadType, "dest-workload-2") + + destProxy1 = resource.ReplaceType(types.ProxyStateTemplateType, destWorkload1) + destProxy2 = resource.ReplaceType(types.ProxyStateTemplateType, destWorkload2) + ) + + // Endpoints for original destination + destEndpoints := resourcetest.ResourceID(resource.ReplaceType(catalog.ServiceEndpointsType, destService.Id)). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, &pbcatalog.ServiceEndpoints{ + Endpoints: []*pbcatalog.Endpoint{ + { + TargetRef: destWorkload1, + Ports: anyWorkloadPorts, + }, + { + TargetRef: destWorkload2, + Ports: anyWorkloadPorts, + }, + }, + }). + Build() + + var ( + targetWorkload1 = newID(catalog.WorkloadType, "target-workload-1") + targetWorkload2 = newID(catalog.WorkloadType, "target-workload-2") + targetWorkload3 = newID(catalog.WorkloadType, "target-workload-3") + backupTargetWorkload1 = newID(catalog.WorkloadType, "backup-target-workload-1") + backupTargetWorkload2 = newID(catalog.WorkloadType, "backup-target-workload-2") + backupTargetWorkload3 = newID(catalog.WorkloadType, "backup-target-workload-3") + + targetProxy1 = resource.ReplaceType(types.ProxyStateTemplateType, targetWorkload1) + targetProxy2 = resource.ReplaceType(types.ProxyStateTemplateType, targetWorkload2) + targetProxy3 = resource.ReplaceType(types.ProxyStateTemplateType, targetWorkload3) + backupTargetProxy1 = resource.ReplaceType(types.ProxyStateTemplateType, backupTargetWorkload1) + backupTargetProxy2 = resource.ReplaceType(types.ProxyStateTemplateType, backupTargetWorkload2) + backupTargetProxy3 = resource.ReplaceType(types.ProxyStateTemplateType, backupTargetWorkload3) + ) + + // Endpoints for actual destination + targetEndpoints := resourcetest.ResourceID(resource.ReplaceType(catalog.ServiceEndpointsType, targetService.Id)). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, &pbcatalog.ServiceEndpoints{ + Endpoints: []*pbcatalog.Endpoint{ + { + TargetRef: targetWorkload1, + Ports: anyWorkloadPorts, + }, + { + TargetRef: targetWorkload2, + Ports: anyWorkloadPorts, + }, + { + TargetRef: targetWorkload3, + Ports: anyWorkloadPorts, + }, + }, + }). + Build() + backupTargetEndpoints := resourcetest.ResourceID(resource.ReplaceType(catalog.ServiceEndpointsType, backupTargetService.Id)). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, &pbcatalog.ServiceEndpoints{ + Endpoints: []*pbcatalog.Endpoint{ + { + TargetRef: backupTargetWorkload1, + Ports: anyWorkloadPorts, + }, + { + TargetRef: backupTargetWorkload2, + Ports: anyWorkloadPorts, + }, + { + TargetRef: backupTargetWorkload3, + Ports: anyWorkloadPorts, + }, + }, + }). + Build() + + var ( + sourceProxy1 = newID(types.ProxyStateTemplateType, "src-workload-1") + sourceProxy2 = newID(types.ProxyStateTemplateType, "src-workload-2") + sourceProxy3 = newID(types.ProxyStateTemplateType, "src-workload-3") + sourceProxy4 = newID(types.ProxyStateTemplateType, "src-workload-4") + sourceProxy5 = newID(types.ProxyStateTemplateType, "src-workload-5") + sourceProxy6 = newID(types.ProxyStateTemplateType, "src-workload-6") + ) + + destination1 := intermediate.CombinedDestinationRef{ + ServiceRef: destServiceRef, + Port: "tcp1", + SourceProxies: map[resource.ReferenceKey]struct{}{ + resource.NewReferenceKey(sourceProxy1): {}, + resource.NewReferenceKey(sourceProxy2): {}, + }, + } + destination2 := intermediate.CombinedDestinationRef{ + ServiceRef: destServiceRef, + Port: "tcp2", + SourceProxies: map[resource.ReferenceKey]struct{}{ + resource.NewReferenceKey(sourceProxy3): {}, + resource.NewReferenceKey(sourceProxy4): {}, + }, + } + destination3 := intermediate.CombinedDestinationRef{ + ServiceRef: destServiceRef, + Port: "mesh", + SourceProxies: map[resource.ReferenceKey]struct{}{ + resource.NewReferenceKey(sourceProxy5): {}, + resource.NewReferenceKey(sourceProxy6): {}, + }, + } + + routesCache.TrackComputedRoutes(webRoutes) + destCache.WriteDestination(destination1) + destCache.WriteDestination(destination2) + destCache.WriteDestination(destination3) + + t.Run("ServiceEndpoints", func(t *testing.T) { + t.Run("map dest endpoints", func(t *testing.T) { + requests, err := mapper.MapServiceEndpointsToProxyStateTemplate( + context.Background(), + controller.Runtime{Client: client}, + destEndpoints, + ) + require.NoError(t, err) + + expRequests := []controller.Request{ + // Just wakeup proxies for these workloads. + {ID: destProxy1}, + {ID: destProxy2}, + } + + prototest.AssertElementsMatch(t, expRequests, requests) + }) + + t.Run("map target endpoints (TCPRoute)", func(t *testing.T) { + requests, err := mapper.MapServiceEndpointsToProxyStateTemplate( + context.Background(), + controller.Runtime{Client: client}, + targetEndpoints, + ) + require.NoError(t, err) + + requests = testDeduplicateRequests(requests) + + expRequests := []controller.Request{ + // Wakeup proxies for these workloads. + {ID: targetProxy1}, + {ID: targetProxy2}, + {ID: targetProxy3}, + // Also wakeup things that have destService as a destination b/c of the TCPRoute reference. + {ID: sourceProxy1}, + {ID: sourceProxy2}, + {ID: sourceProxy3}, + {ID: sourceProxy4}, + {ID: sourceProxy5}, + {ID: sourceProxy6}, + } + + prototest.AssertElementsMatch(t, expRequests, requests) + }) + + t.Run("map backup target endpoints (FailoverPolicy)", func(t *testing.T) { + requests, err := mapper.MapServiceEndpointsToProxyStateTemplate( + context.Background(), + controller.Runtime{Client: client}, + backupTargetEndpoints, + ) + require.NoError(t, err) + + requests = testDeduplicateRequests(requests) + + expRequests := []controller.Request{ + // Wakeup proxies for these workloads. + {ID: backupTargetProxy1}, + {ID: backupTargetProxy2}, + {ID: backupTargetProxy3}, + // Also wakeup things that have destService as a destination b/c of the FailoverPolicy reference. + {ID: sourceProxy1}, + {ID: sourceProxy2}, + {ID: sourceProxy3}, + {ID: sourceProxy4}, + {ID: sourceProxy5}, + {ID: sourceProxy6}, + } + + prototest.AssertElementsMatch(t, expRequests, requests) + }) + }) + + t.Run("Service", func(t *testing.T) { + t.Run("map dest service", func(t *testing.T) { + requests, err := mapper.MapServiceToProxyStateTemplate( + context.Background(), + controller.Runtime{Client: client}, + destService, + ) + require.NoError(t, err) + + // Only wake up things with dest as an upstream. + expRequests := []controller.Request{ + {ID: sourceProxy1}, + {ID: sourceProxy2}, + {ID: sourceProxy3}, + {ID: sourceProxy4}, + {ID: sourceProxy5}, + {ID: sourceProxy6}, + } + + prototest.AssertElementsMatch(t, expRequests, requests) + }) + + t.Run("map target endpoints (TCPRoute)", func(t *testing.T) { + requests, err := mapper.MapServiceToProxyStateTemplate( + context.Background(), + controller.Runtime{Client: client}, + targetService, + ) + require.NoError(t, err) + + requests = testDeduplicateRequests(requests) + + // No upstream referrs to target directly. + expRequests := []controller.Request{} + + prototest.AssertElementsMatch(t, expRequests, requests) + }) + }) + + t.Run("ComputedRoutes", func(t *testing.T) { + t.Run("map web routes", func(t *testing.T) { + requests, err := mapper.MapComputedRoutesToProxyStateTemplate( + context.Background(), + controller.Runtime{Client: client}, + webRoutes.Resource, + ) + require.NoError(t, err) + + // Only wake up things with dest as an upstream. + expRequests := []controller.Request{ + {ID: sourceProxy1}, + {ID: sourceProxy2}, + {ID: sourceProxy3}, + {ID: sourceProxy4}, + {ID: sourceProxy5}, + {ID: sourceProxy6}, + } + + prototest.AssertElementsMatch(t, expRequests, requests) + }) + }) +} + +func newRef(typ *pbresource.Type, name string) *pbresource.Reference { + return resource.Reference(newID(typ, name), "") +} + +func newID(typ *pbresource.Type, name string) *pbresource.ID { + return &pbresource.ID{ + Type: typ, + Tenancy: resource.DefaultNamespacedTenancy(), + Name: name, + } +} + +func testDeduplicateRequests(reqs []controller.Request) []controller.Request { + type resID struct { + resource.ReferenceKey + UID string + } + + out := make([]controller.Request, 0, len(reqs)) + seen := make(map[resID]struct{}) + + for _, req := range reqs { + rid := resID{ + ReferenceKey: resource.NewReferenceKey(req.ID), + UID: req.ID.Uid, + } + if _, ok := seen[rid]; !ok { + out = append(out, req) + seen[rid] = struct{}{} + } + } + + return out +} diff --git a/internal/mesh/internal/types/computed_routes.go b/internal/mesh/internal/types/computed_routes.go index fc0834abfb6b..d4407ae5867a 100644 --- a/internal/mesh/internal/types/computed_routes.go +++ b/internal/mesh/internal/types/computed_routes.go @@ -4,6 +4,8 @@ package types import ( + "fmt" + "github.com/hashicorp/go-multierror" "github.com/hashicorp/consul/internal/resource" @@ -72,6 +74,40 @@ func ValidateComputedRoutes(res *pbresource.Resource) error { })) } + for targetName, target := range pmc.Targets { + wrapTargetErr := func(err error) error { + return wrapErr(resource.ErrInvalidMapValue{ + Map: "targets", + Key: targetName, + Wrapped: err, + }) + } + if target.MeshPort == "" { + merr = multierror.Append(merr, wrapTargetErr(resource.ErrInvalidField{ + Name: "mesh_port", + Wrapped: resource.ErrEmpty, + })) + } + if target.ServiceEndpointsId != nil { + merr = multierror.Append(merr, wrapTargetErr(resource.ErrInvalidField{ + Name: "service_endpoints_id", + Wrapped: fmt.Errorf("field should be empty"), + })) + } + if target.ServiceEndpoints != nil { + merr = multierror.Append(merr, wrapTargetErr(resource.ErrInvalidField{ + Name: "service_endpoints", + Wrapped: fmt.Errorf("field should be empty"), + })) + } + if len(target.IdentityRefs) > 0 { + merr = multierror.Append(merr, wrapTargetErr(resource.ErrInvalidField{ + Name: "identity_refs", + Wrapped: fmt.Errorf("field should be empty"), + })) + } + } + // TODO(rb): do a deep inspection of the config to verify that all // xRoute backends ultimately point to an item in the targets map. } diff --git a/internal/mesh/internal/types/computed_routes_test.go b/internal/mesh/internal/types/computed_routes_test.go index 9967acda7521..3079bfebbde4 100644 --- a/internal/mesh/internal/types/computed_routes_test.go +++ b/internal/mesh/internal/types/computed_routes_test.go @@ -9,7 +9,9 @@ import ( "github.com/stretchr/testify/require" "github.com/hashicorp/consul/internal/resource/resourcetest" + pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/proto/private/prototest" "github.com/hashicorp/consul/sdk/testutil" ) @@ -53,6 +55,79 @@ func TestValidateComputedRoutes(t *testing.T) { }, expectErr: `invalid value of key "http" within ported_configs: invalid "config" field: cannot be empty`, }, + "target/missing mesh port": { + routes: &pbmesh.ComputedRoutes{ + PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ + "http": { + Config: &pbmesh.ComputedPortRoutes_Tcp{ + Tcp: &pbmesh.ComputedTCPRoute{}, + }, + Targets: map[string]*pbmesh.BackendTargetDetails{ + "foo": { + MeshPort: "", + }, + }, + }, + }, + }, + expectErr: `invalid value of key "http" within ported_configs: invalid value of key "foo" within targets: invalid "mesh_port" field: cannot be empty`, + }, + "target/should not have service endpoints id": { + routes: &pbmesh.ComputedRoutes{ + PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ + "http": { + Config: &pbmesh.ComputedPortRoutes_Tcp{ + Tcp: &pbmesh.ComputedTCPRoute{}, + }, + Targets: map[string]*pbmesh.BackendTargetDetails{ + "foo": { + MeshPort: "mesh", + ServiceEndpointsId: &pbresource.ID{}, + }, + }, + }, + }, + }, + expectErr: `invalid value of key "http" within ported_configs: invalid value of key "foo" within targets: invalid "service_endpoints_id" field: field should be empty`, + }, + "target/should not have service endpoints": { + routes: &pbmesh.ComputedRoutes{ + PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ + "http": { + Config: &pbmesh.ComputedPortRoutes_Tcp{ + Tcp: &pbmesh.ComputedTCPRoute{}, + }, + Targets: map[string]*pbmesh.BackendTargetDetails{ + "foo": { + MeshPort: "mesh", + ServiceEndpoints: &pbcatalog.ServiceEndpoints{}, + }, + }, + }, + }, + }, + expectErr: `invalid value of key "http" within ported_configs: invalid value of key "foo" within targets: invalid "service_endpoints" field: field should be empty`, + }, + "target/should not have identity refs": { + routes: &pbmesh.ComputedRoutes{ + PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ + "http": { + Config: &pbmesh.ComputedPortRoutes_Tcp{ + Tcp: &pbmesh.ComputedTCPRoute{}, + }, + Targets: map[string]*pbmesh.BackendTargetDetails{ + "foo": { + MeshPort: "mesh", + IdentityRefs: []*pbresource.Reference{ + {}, + }, + }, + }, + }, + }, + }, + expectErr: `invalid value of key "http" within ported_configs: invalid value of key "foo" within targets: invalid "identity_refs" field: field should be empty`, + }, "valid": { routes: &pbmesh.ComputedRoutes{ PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ @@ -61,7 +136,9 @@ func TestValidateComputedRoutes(t *testing.T) { Tcp: &pbmesh.ComputedTCPRoute{}, }, Targets: map[string]*pbmesh.BackendTargetDetails{ - "foo": {}, + "foo": { + MeshPort: "mesh", + }, }, }, }, diff --git a/internal/mesh/internal/types/decoded.go b/internal/mesh/internal/types/decoded.go index 90ce21233327..50fb4d04b496 100644 --- a/internal/mesh/internal/types/decoded.go +++ b/internal/mesh/internal/types/decoded.go @@ -10,11 +10,16 @@ import ( ) type ( - DecodedHTTPRoute = resource.DecodedResource[*pbmesh.HTTPRoute] - DecodedGRPCRoute = resource.DecodedResource[*pbmesh.GRPCRoute] - DecodedTCPRoute = resource.DecodedResource[*pbmesh.TCPRoute] - DecodedDestinationPolicy = resource.DecodedResource[*pbmesh.DestinationPolicy] - DecodedComputedRoutes = resource.DecodedResource[*pbmesh.ComputedRoutes] - DecodedFailoverPolicy = resource.DecodedResource[*pbcatalog.FailoverPolicy] - DecodedService = resource.DecodedResource[*pbcatalog.Service] + DecodedHTTPRoute = resource.DecodedResource[*pbmesh.HTTPRoute] + DecodedGRPCRoute = resource.DecodedResource[*pbmesh.GRPCRoute] + DecodedTCPRoute = resource.DecodedResource[*pbmesh.TCPRoute] + DecodedDestinationPolicy = resource.DecodedResource[*pbmesh.DestinationPolicy] + DecodedComputedRoutes = resource.DecodedResource[*pbmesh.ComputedRoutes] + DecodedFailoverPolicy = resource.DecodedResource[*pbcatalog.FailoverPolicy] + DecodedService = resource.DecodedResource[*pbcatalog.Service] + DecodedServiceEndpoints = resource.DecodedResource[*pbcatalog.ServiceEndpoints] + DecodedWorkload = resource.DecodedResource[*pbcatalog.Workload] + DecodedProxyConfiguration = resource.DecodedResource[*pbmesh.ProxyConfiguration] + DecodedDestinations = resource.DecodedResource[*pbmesh.Upstreams] + DecodedProxyStateTemplate = resource.DecodedResource[*pbmesh.ProxyStateTemplate] ) diff --git a/internal/mesh/internal/types/http_route_test.go b/internal/mesh/internal/types/http_route_test.go index ba2342f14ed5..5b9a0ee42c85 100644 --- a/internal/mesh/internal/types/http_route_test.go +++ b/internal/mesh/internal/types/http_route_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/wrapperspb" "github.com/hashicorp/consul/internal/catalog" "github.com/hashicorp/consul/internal/resource" @@ -941,12 +942,6 @@ type xRouteRetriesTestcase struct { func getXRouteRetriesTestCases() map[string]xRouteRetriesTestcase { return map[string]xRouteRetriesTestcase{ - "bad number": { - retries: &pbmesh.HTTPRouteRetries{ - Number: -5, - }, - expectErr: `invalid element at index 0 of list "rules": invalid "retries" field: invalid "number" field: cannot be negative: -5`, - }, "bad conditions": { retries: &pbmesh.HTTPRouteRetries{ OnConditions: []string{"garbage"}, @@ -955,7 +950,7 @@ func getXRouteRetriesTestCases() map[string]xRouteRetriesTestcase { }, "good all": { retries: &pbmesh.HTTPRouteRetries{ - Number: 5, + Number: wrapperspb.UInt32(5), OnConditions: []string{"internal"}, }, }, @@ -963,7 +958,9 @@ func getXRouteRetriesTestCases() map[string]xRouteRetriesTestcase { } func newRef(typ *pbresource.Type, name string) *pbresource.Reference { - return resourcetest.Resource(typ, name).WithTenancy(resource.DefaultNamespacedTenancy()).Reference("") + return resourcetest.Resource(typ, name). + WithTenancy(resource.DefaultNamespacedTenancy()). + Reference("") } func newBackendRef(typ *pbresource.Type, name, port string) *pbmesh.BackendReference { diff --git a/internal/mesh/internal/types/intermediate/types.go b/internal/mesh/internal/types/intermediate/types.go index ea4c449f5b52..c9befcfbd6d3 100644 --- a/internal/mesh/internal/types/intermediate/types.go +++ b/internal/mesh/internal/types/intermediate/types.go @@ -4,8 +4,8 @@ package intermediate import ( + "github.com/hashicorp/consul/internal/mesh/internal/types" "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" "github.com/hashicorp/consul/proto-public/pbresource" ) @@ -27,41 +27,11 @@ type CombinedDestinationRef struct { ExplicitDestinationsID *pbresource.ID } -type ServiceEndpoints struct { - Resource *pbresource.Resource - Endpoints *pbcatalog.ServiceEndpoints -} - -type Service struct { - Resource *pbresource.Resource - Service *pbcatalog.Service -} - -type Destinations struct { - Resource *pbresource.Resource - Destinations *pbmesh.Upstreams -} - -type Workload struct { - Resource *pbresource.Resource - Workload *pbcatalog.Workload -} - -type ProxyStateTemplate struct { - Resource *pbresource.Resource - Tmpl *pbmesh.ProxyStateTemplate -} - -type ProxyConfiguration struct { - Resource *pbresource.Resource - Cfg *pbmesh.ProxyConfiguration -} - type Destination struct { - Explicit *pbmesh.Upstream - ServiceEndpoints *ServiceEndpoints - Identities []*pbresource.Reference - VirtualIPs []string + Explicit *pbmesh.Upstream + Service *types.DecodedService // for the name of this destination + VirtualIPs []string // for the name of this destination + ComputedPortRoutes *pbmesh.ComputedPortRoutes // for the name of this destination } type Status struct { diff --git a/internal/mesh/internal/types/tcp_route.go b/internal/mesh/internal/types/tcp_route.go index 5dc59228aa7f..8549b1c33f37 100644 --- a/internal/mesh/internal/types/tcp_route.go +++ b/internal/mesh/internal/types/tcp_route.go @@ -4,6 +4,8 @@ package types import ( + "fmt" + "github.com/hashicorp/go-multierror" "github.com/hashicorp/consul/internal/resource" @@ -48,6 +50,13 @@ func ValidateTCPRoute(res *pbresource.Resource) error { merr = multierror.Append(merr, err) } + if len(route.Rules) > 1 { + merr = multierror.Append(merr, resource.ErrInvalidField{ + Name: "rules", + Wrapped: fmt.Errorf("must only specify a single rule for now"), + }) + } + for i, rule := range route.Rules { wrapRuleErr := func(err error) error { return resource.ErrInvalidListElement{ diff --git a/internal/mesh/internal/types/tcp_route_test.go b/internal/mesh/internal/types/tcp_route_test.go index 2fefe2783d48..6469ada83b50 100644 --- a/internal/mesh/internal/types/tcp_route_test.go +++ b/internal/mesh/internal/types/tcp_route_test.go @@ -41,7 +41,35 @@ func TestValidateTCPRoute(t *testing.T) { } } - cases := map[string]testcase{} + cases := map[string]testcase{ + "no rules": { + route: &pbmesh.TCPRoute{ + ParentRefs: []*pbmesh.ParentReference{ + newParentRef(catalog.ServiceType, "web", ""), + }, + }, + }, + "more than one rule": { + route: &pbmesh.TCPRoute{ + ParentRefs: []*pbmesh.ParentReference{ + newParentRef(catalog.ServiceType, "web", ""), + }, + Rules: []*pbmesh.TCPRouteRule{ + { + BackendRefs: []*pbmesh.TCPBackendRef{{ + BackendRef: newBackendRef(catalog.ServiceType, "api", ""), + }}, + }, + { + BackendRefs: []*pbmesh.TCPBackendRef{{ + BackendRef: newBackendRef(catalog.ServiceType, "db", ""), + }}, + }, + }, + }, + expectErr: `invalid "rules" field: must only specify a single rule for now`, + }, + } // Add common parent refs test cases. for name, parentTC := range getXRouteParentRefTestCases() { diff --git a/internal/mesh/internal/types/xroute.go b/internal/mesh/internal/types/xroute.go index e9fe6df38260..b29f9a61064b 100644 --- a/internal/mesh/internal/types/xroute.go +++ b/internal/mesh/internal/types/xroute.go @@ -275,13 +275,6 @@ func validateHTTPRetries(retries *pbmesh.HTTPRouteRetries) []error { var errs []error - if retries.Number < 0 { - errs = append(errs, resource.ErrInvalidField{ - Name: "number", - Wrapped: fmt.Errorf("cannot be negative: %v", retries.Number), - }) - } - for i, condition := range retries.OnConditions { if !isValidRetryCondition(condition) { errs = append(errs, resource.ErrInvalidListElement{ diff --git a/internal/protohcl/primitives.go b/internal/protohcl/primitives.go index 4d1f22033026..c93218c99748 100644 --- a/internal/protohcl/primitives.go +++ b/internal/protohcl/primitives.go @@ -63,14 +63,20 @@ func protoEnumFromCty(desc protoreflect.FieldDescriptor, val cty.Value) (protore } if val.IsNull() { - defaultValDesc := desc.DefaultEnumValue() - return protoreflect.ValueOfEnum(defaultValDesc.Number()), nil + if desc.HasDefault() { + defaultValDesc := desc.DefaultEnumValue() + return protoreflect.ValueOfEnum(defaultValDesc.Number()), nil + } + return protoreflect.Value{}, fmt.Errorf("no default value for type and value is null") } valDesc := desc.Enum().Values().ByName(protoreflect.Name(val.AsString())) if valDesc == nil { - defaultValDesc := desc.DefaultEnumValue() - return protoreflect.ValueOfEnum(defaultValDesc.Number()), nil + if desc.HasDefault() { + defaultValDesc := desc.DefaultEnumValue() + return protoreflect.ValueOfEnum(defaultValDesc.Number()), nil + } + return protoreflect.Value{}, fmt.Errorf("no default value for type and value is invalid") } return protoreflect.ValueOfEnum(valDesc.Number()), nil diff --git a/internal/resource/reference.go b/internal/resource/reference.go index d5eafe292c81..a2ff0588acf0 100644 --- a/internal/resource/reference.go +++ b/internal/resource/reference.go @@ -38,6 +38,20 @@ var ( _ ReferenceOrID = (*pbresource.Reference)(nil) ) +func ReferenceFromReferenceOrID(ref ReferenceOrID) *pbresource.Reference { + switch x := ref.(type) { + case *pbresource.Reference: + return x + default: + return &pbresource.Reference{ + Type: ref.GetType(), + Tenancy: ref.GetTenancy(), + Name: ref.GetName(), + Section: "", + } + } +} + func ReplaceType(typ *pbresource.Type, id *pbresource.ID) *pbresource.ID { return &pbresource.ID{ Type: typ, diff --git a/internal/resourcehcl/any.go b/internal/resourcehcl/any.go index 3d797c48e5b8..71086f655de0 100644 --- a/internal/resourcehcl/any.go +++ b/internal/resourcehcl/any.go @@ -34,12 +34,15 @@ func (p anyProvider) AnyType(ctx *protohcl.UnmarshalContext, decoder protohcl.Me if !isResource { return p.base.AnyType(ctx, decoder) } - - resourceType := res.GetId().GetType() if res == nil { return "", nil, errors.New("ID.Type not found") } + resourceType := res.GetId().GetType() + if resourceType == nil { + return "", nil, errors.New("ID.Type is nil") + } + reg, ok := p.reg.Resolve(resourceType) if !ok { return "", nil, fmt.Errorf("unknown resource type: %s", resource.ToGVK(resourceType)) diff --git a/internal/resourcehcl/naming.go b/internal/resourcehcl/naming.go index a1160cc32363..590ea067886d 100644 --- a/internal/resourcehcl/naming.go +++ b/internal/resourcehcl/naming.go @@ -33,6 +33,9 @@ func (n fieldNamer) GetField(fds protoreflect.FieldDescriptors, name string) pro } } + if len(name) <= 1 { + return fds.ByJSONName(name) + } camel := strings.ToLower(name[:1]) + name[1:] return fds.ByJSONName(camel) } diff --git a/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/0e4b8ec300611dbc b/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/0e4b8ec300611dbc new file mode 100644 index 000000000000..7f8a2357c738 --- /dev/null +++ b/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/0e4b8ec300611dbc @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("Data{}") diff --git a/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/c800420b7494c6d1 b/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/c800420b7494c6d1 new file mode 100644 index 000000000000..3d99674458c2 --- /dev/null +++ b/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/c800420b7494c6d1 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("ID={\"\"=\"\"}") diff --git a/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/eaba8205942c3f31 b/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/eaba8205942c3f31 new file mode 100644 index 000000000000..b63214c55a5f --- /dev/null +++ b/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/eaba8205942c3f31 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("ID {\nType = gvk(\"demo.v1.Artist\")\n} \nData {\nGenre = \"\"\n} ") diff --git a/internal/resourcehcl/unmarshal_test.go b/internal/resourcehcl/unmarshal_test.go index 5e35f7df66b1..e5b650674472 100644 --- a/internal/resourcehcl/unmarshal_test.go +++ b/internal/resourcehcl/unmarshal_test.go @@ -23,6 +23,47 @@ import ( var update = flag.Bool("update", false, "update golden files") +func FuzzUnmarshall(f *testing.F) { + entries, err := os.ReadDir("./testdata") + require.NoError(f, err) + + read := func(t *testing.F, path string) ([]byte, bool) { + t.Helper() + + bytes, err := os.ReadFile(fmt.Sprintf("./testdata/%s", path)) + switch { + case err == nil: + return bytes, true + case os.IsNotExist(err): + return nil, false + } + + t.Fatalf("failed to read file %s %v", path, err) + return nil, false + } + for _, entry := range entries { + ext := path.Ext(entry.Name()) + + if ext != ".hcl" { + continue + } + input, _ := read(f, entry.Name()) + f.Add(input) + } + registry := resource.NewRegistry() + demo.RegisterTypes(registry) + mesh.RegisterTypes(registry) + + f.Fuzz(func(t *testing.T, input []byte) { + got, err := resourcehcl.Unmarshal(input, registry) + if err != nil { + return + } + require.NotNil(t, got) + }) + +} + func TestUnmarshal(t *testing.T) { entries, err := os.ReadDir("./testdata") require.NoError(t, err) diff --git a/proto-public/pbauth/v1alpha1/computed_traffic_permissions.pb.binary.go b/proto-public/pbauth/v1alpha1/computed_traffic_permissions.pb.binary.go new file mode 100644 index 000000000000..30e21ec22094 --- /dev/null +++ b/proto-public/pbauth/v1alpha1/computed_traffic_permissions.pb.binary.go @@ -0,0 +1,18 @@ +// Code generated by protoc-gen-go-binary. DO NOT EDIT. +// source: pbauth/v1alpha1/computed_traffic_permissions.proto + +package authv1alpha1 + +import ( + "google.golang.org/protobuf/proto" +) + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *ComputedTrafficPermissions) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *ComputedTrafficPermissions) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} diff --git a/proto-public/pbauth/v1alpha1/computed_traffic_permissions.pb.go b/proto-public/pbauth/v1alpha1/computed_traffic_permissions.pb.go new file mode 100644 index 000000000000..9d816be90e69 --- /dev/null +++ b/proto-public/pbauth/v1alpha1/computed_traffic_permissions.pb.go @@ -0,0 +1,188 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc (unknown) +// source: pbauth/v1alpha1/computed_traffic_permissions.proto + +package authv1alpha1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ComputedTrafficPermissions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AllowPermissions []*Permission `protobuf:"bytes,1,rep,name=allow_permissions,json=allowPermissions,proto3" json:"allow_permissions,omitempty"` + DenyPermissions []*Permission `protobuf:"bytes,2,rep,name=deny_permissions,json=denyPermissions,proto3" json:"deny_permissions,omitempty"` +} + +func (x *ComputedTrafficPermissions) Reset() { + *x = ComputedTrafficPermissions{} + if protoimpl.UnsafeEnabled { + mi := &file_pbauth_v1alpha1_computed_traffic_permissions_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ComputedTrafficPermissions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ComputedTrafficPermissions) ProtoMessage() {} + +func (x *ComputedTrafficPermissions) ProtoReflect() protoreflect.Message { + mi := &file_pbauth_v1alpha1_computed_traffic_permissions_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ComputedTrafficPermissions.ProtoReflect.Descriptor instead. +func (*ComputedTrafficPermissions) Descriptor() ([]byte, []int) { + return file_pbauth_v1alpha1_computed_traffic_permissions_proto_rawDescGZIP(), []int{0} +} + +func (x *ComputedTrafficPermissions) GetAllowPermissions() []*Permission { + if x != nil { + return x.AllowPermissions + } + return nil +} + +func (x *ComputedTrafficPermissions) GetDenyPermissions() []*Permission { + if x != nil { + return x.DenyPermissions + } + return nil +} + +var File_pbauth_v1alpha1_computed_traffic_permissions_proto protoreflect.FileDescriptor + +var file_pbauth_v1alpha1_computed_traffic_permissions_proto_rawDesc = []byte{ + 0x0a, 0x32, 0x70, 0x62, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x72, 0x61, 0x66, 0x66, + 0x69, 0x63, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x1a, 0x29, 0x70, 0x62, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x70, 0x65, + 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, + 0xcc, 0x01, 0x0a, 0x1a, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x66, + 0x66, 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x57, + 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x50, 0x65, 0x72, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x55, 0x0a, 0x10, 0x64, 0x65, 0x6e, 0x79, 0x5f, + 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x64, + 0x65, 0x6e, 0x79, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0xa7, + 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x1f, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x54, + 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x3b, 0x61, 0x75, 0x74, 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, + 0x02, 0x03, 0x48, 0x43, 0x41, 0xaa, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x2e, 0x56, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x41, 0x75, 0x74, 0x68, 0x5c, + 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x41, 0x75, 0x74, 0x68, 0x3a, 0x3a, + 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pbauth_v1alpha1_computed_traffic_permissions_proto_rawDescOnce sync.Once + file_pbauth_v1alpha1_computed_traffic_permissions_proto_rawDescData = file_pbauth_v1alpha1_computed_traffic_permissions_proto_rawDesc +) + +func file_pbauth_v1alpha1_computed_traffic_permissions_proto_rawDescGZIP() []byte { + file_pbauth_v1alpha1_computed_traffic_permissions_proto_rawDescOnce.Do(func() { + file_pbauth_v1alpha1_computed_traffic_permissions_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbauth_v1alpha1_computed_traffic_permissions_proto_rawDescData) + }) + return file_pbauth_v1alpha1_computed_traffic_permissions_proto_rawDescData +} + +var file_pbauth_v1alpha1_computed_traffic_permissions_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_pbauth_v1alpha1_computed_traffic_permissions_proto_goTypes = []interface{}{ + (*ComputedTrafficPermissions)(nil), // 0: hashicorp.consul.auth.v1alpha1.ComputedTrafficPermissions + (*Permission)(nil), // 1: hashicorp.consul.auth.v1alpha1.Permission +} +var file_pbauth_v1alpha1_computed_traffic_permissions_proto_depIdxs = []int32{ + 1, // 0: hashicorp.consul.auth.v1alpha1.ComputedTrafficPermissions.allow_permissions:type_name -> hashicorp.consul.auth.v1alpha1.Permission + 1, // 1: hashicorp.consul.auth.v1alpha1.ComputedTrafficPermissions.deny_permissions:type_name -> hashicorp.consul.auth.v1alpha1.Permission + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_pbauth_v1alpha1_computed_traffic_permissions_proto_init() } +func file_pbauth_v1alpha1_computed_traffic_permissions_proto_init() { + if File_pbauth_v1alpha1_computed_traffic_permissions_proto != nil { + return + } + file_pbauth_v1alpha1_traffic_permissions_proto_init() + if !protoimpl.UnsafeEnabled { + file_pbauth_v1alpha1_computed_traffic_permissions_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ComputedTrafficPermissions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pbauth_v1alpha1_computed_traffic_permissions_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pbauth_v1alpha1_computed_traffic_permissions_proto_goTypes, + DependencyIndexes: file_pbauth_v1alpha1_computed_traffic_permissions_proto_depIdxs, + MessageInfos: file_pbauth_v1alpha1_computed_traffic_permissions_proto_msgTypes, + }.Build() + File_pbauth_v1alpha1_computed_traffic_permissions_proto = out.File + file_pbauth_v1alpha1_computed_traffic_permissions_proto_rawDesc = nil + file_pbauth_v1alpha1_computed_traffic_permissions_proto_goTypes = nil + file_pbauth_v1alpha1_computed_traffic_permissions_proto_depIdxs = nil +} diff --git a/proto-public/pbauth/v1alpha1/computed_traffic_permissions.proto b/proto-public/pbauth/v1alpha1/computed_traffic_permissions.proto new file mode 100644 index 000000000000..fb43f553fe9a --- /dev/null +++ b/proto-public/pbauth/v1alpha1/computed_traffic_permissions.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +package hashicorp.consul.auth.v1alpha1; + +import "pbauth/v1alpha1/traffic_permissions.proto"; + +message ComputedTrafficPermissions { + repeated Permission allow_permissions = 1; + repeated Permission deny_permissions = 2; +} diff --git a/proto-public/pbauth/v1alpha1/traffic_permissions.pb.binary.go b/proto-public/pbauth/v1alpha1/traffic_permissions.pb.binary.go new file mode 100644 index 000000000000..4ae5d3d17c78 --- /dev/null +++ b/proto-public/pbauth/v1alpha1/traffic_permissions.pb.binary.go @@ -0,0 +1,108 @@ +// Code generated by protoc-gen-go-binary. DO NOT EDIT. +// source: pbauth/v1alpha1/traffic_permissions.proto + +package authv1alpha1 + +import ( + "google.golang.org/protobuf/proto" +) + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *TrafficPermissions) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *TrafficPermissions) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *NamespaceTrafficPermissions) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *NamespaceTrafficPermissions) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *PartitionTrafficPermissions) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *PartitionTrafficPermissions) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *Destination) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *Destination) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *Permission) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *Permission) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *Source) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *Source) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *ExcludeSource) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *ExcludeSource) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *DestinationRule) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *DestinationRule) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *ExcludePermissionRule) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *ExcludePermissionRule) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *DestinationRuleHeader) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *DestinationRuleHeader) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} diff --git a/proto-public/pbauth/v1alpha1/traffic_permissions.pb.go b/proto-public/pbauth/v1alpha1/traffic_permissions.pb.go new file mode 100644 index 000000000000..1966c4a1c870 --- /dev/null +++ b/proto-public/pbauth/v1alpha1/traffic_permissions.pb.go @@ -0,0 +1,1191 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc (unknown) +// source: pbauth/v1alpha1/traffic_permissions.proto + +package authv1alpha1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Action int32 + +const ( + Action_ACTION_UNSPECIFIED Action = 0 + Action_ACTION_DENY Action = 1 + Action_ACTION_ALLOW Action = 2 +) + +// Enum value maps for Action. +var ( + Action_name = map[int32]string{ + 0: "ACTION_UNSPECIFIED", + 1: "ACTION_DENY", + 2: "ACTION_ALLOW", + } + Action_value = map[string]int32{ + "ACTION_UNSPECIFIED": 0, + "ACTION_DENY": 1, + "ACTION_ALLOW": 2, + } +) + +func (x Action) Enum() *Action { + p := new(Action) + *p = x + return p +} + +func (x Action) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Action) Descriptor() protoreflect.EnumDescriptor { + return file_pbauth_v1alpha1_traffic_permissions_proto_enumTypes[0].Descriptor() +} + +func (Action) Type() protoreflect.EnumType { + return &file_pbauth_v1alpha1_traffic_permissions_proto_enumTypes[0] +} + +func (x Action) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Action.Descriptor instead. +func (Action) EnumDescriptor() ([]byte, []int) { + return file_pbauth_v1alpha1_traffic_permissions_proto_rawDescGZIP(), []int{0} +} + +type TrafficPermissions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // destination is a configuration of the destination proxies + // where these traffic permissions should apply. + Destination *Destination `protobuf:"bytes,1,opt,name=destination,proto3" json:"destination,omitempty"` + // Action can be either allow or deny for the entire object. It will default to allow. + // + // If action is allow, + // we will allow the connection if one of the rules in Rules matches, in other words, we will deny + // all requests except for the ones that match Rules. If Consul is in default allow mode, then allow + // actions have no effect without a deny permission as everything is allowed by default. + // + // If action is deny, + // we will deny the connection if one of the rules in Rules match, in other words, + // we will allow all requests except for the ones that match Rules. If Consul is default deny mode, + // then deny permissions have no effect without an allow permission as everything is denied by default. + // + // Action unspecified is reserved for compatibility with the addition of future actions. + Action Action `protobuf:"varint,2,opt,name=action,proto3,enum=hashicorp.consul.auth.v1alpha1.Action" json:"action,omitempty"` + // permissions is a list of permissions to match on. + // They are applied using OR semantics. + Permissions []*Permission `protobuf:"bytes,3,rep,name=permissions,proto3" json:"permissions,omitempty"` +} + +func (x *TrafficPermissions) Reset() { + *x = TrafficPermissions{} + if protoimpl.UnsafeEnabled { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TrafficPermissions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TrafficPermissions) ProtoMessage() {} + +func (x *TrafficPermissions) ProtoReflect() protoreflect.Message { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TrafficPermissions.ProtoReflect.Descriptor instead. +func (*TrafficPermissions) Descriptor() ([]byte, []int) { + return file_pbauth_v1alpha1_traffic_permissions_proto_rawDescGZIP(), []int{0} +} + +func (x *TrafficPermissions) GetDestination() *Destination { + if x != nil { + return x.Destination + } + return nil +} + +func (x *TrafficPermissions) GetAction() Action { + if x != nil { + return x.Action + } + return Action_ACTION_UNSPECIFIED +} + +func (x *TrafficPermissions) GetPermissions() []*Permission { + if x != nil { + return x.Permissions + } + return nil +} + +type NamespaceTrafficPermissions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Action Action `protobuf:"varint,1,opt,name=action,proto3,enum=hashicorp.consul.auth.v1alpha1.Action" json:"action,omitempty"` + Permissions []*Permission `protobuf:"bytes,2,rep,name=permissions,proto3" json:"permissions,omitempty"` +} + +func (x *NamespaceTrafficPermissions) Reset() { + *x = NamespaceTrafficPermissions{} + if protoimpl.UnsafeEnabled { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NamespaceTrafficPermissions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NamespaceTrafficPermissions) ProtoMessage() {} + +func (x *NamespaceTrafficPermissions) ProtoReflect() protoreflect.Message { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NamespaceTrafficPermissions.ProtoReflect.Descriptor instead. +func (*NamespaceTrafficPermissions) Descriptor() ([]byte, []int) { + return file_pbauth_v1alpha1_traffic_permissions_proto_rawDescGZIP(), []int{1} +} + +func (x *NamespaceTrafficPermissions) GetAction() Action { + if x != nil { + return x.Action + } + return Action_ACTION_UNSPECIFIED +} + +func (x *NamespaceTrafficPermissions) GetPermissions() []*Permission { + if x != nil { + return x.Permissions + } + return nil +} + +type PartitionTrafficPermissions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Action Action `protobuf:"varint,1,opt,name=action,proto3,enum=hashicorp.consul.auth.v1alpha1.Action" json:"action,omitempty"` + Permissions []*Permission `protobuf:"bytes,2,rep,name=permissions,proto3" json:"permissions,omitempty"` +} + +func (x *PartitionTrafficPermissions) Reset() { + *x = PartitionTrafficPermissions{} + if protoimpl.UnsafeEnabled { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PartitionTrafficPermissions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PartitionTrafficPermissions) ProtoMessage() {} + +func (x *PartitionTrafficPermissions) ProtoReflect() protoreflect.Message { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PartitionTrafficPermissions.ProtoReflect.Descriptor instead. +func (*PartitionTrafficPermissions) Descriptor() ([]byte, []int) { + return file_pbauth_v1alpha1_traffic_permissions_proto_rawDescGZIP(), []int{2} +} + +func (x *PartitionTrafficPermissions) GetAction() Action { + if x != nil { + return x.Action + } + return Action_ACTION_UNSPECIFIED +} + +func (x *PartitionTrafficPermissions) GetPermissions() []*Permission { + if x != nil { + return x.Permissions + } + return nil +} + +// Destination contains the name or name-prefix of the WorkloadIdentity. +// The WorkloadIdentity resource must +// be in the same tenancy as the TrafficPermissions resource. +type Destination struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IdentityName string `protobuf:"bytes,1,opt,name=identity_name,json=identityName,proto3" json:"identity_name,omitempty"` + IdentityPrefix string `protobuf:"bytes,2,opt,name=identity_prefix,json=identityPrefix,proto3" json:"identity_prefix,omitempty"` +} + +func (x *Destination) Reset() { + *x = Destination{} + if protoimpl.UnsafeEnabled { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Destination) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Destination) ProtoMessage() {} + +func (x *Destination) ProtoReflect() protoreflect.Message { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Destination.ProtoReflect.Descriptor instead. +func (*Destination) Descriptor() ([]byte, []int) { + return file_pbauth_v1alpha1_traffic_permissions_proto_rawDescGZIP(), []int{3} +} + +func (x *Destination) GetIdentityName() string { + if x != nil { + return x.IdentityName + } + return "" +} + +func (x *Destination) GetIdentityPrefix() string { + if x != nil { + return x.IdentityPrefix + } + return "" +} + +// permissions is a list of permissions to match on. +type Permission struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // sources is a list of sources in this traffic permission. + Sources []*Source `protobuf:"bytes,1,rep,name=sources,proto3" json:"sources,omitempty"` + // destination_rules is a list of rules to apply for matching sources in this Permission. + // These rules are specific to the request or connection that is going to the destination(s) + // selected by the TrafficPermissions resource. + DestinationRules []*DestinationRule `protobuf:"bytes,2,rep,name=destination_rules,json=destinationRules,proto3" json:"destination_rules,omitempty"` +} + +func (x *Permission) Reset() { + *x = Permission{} + if protoimpl.UnsafeEnabled { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Permission) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Permission) ProtoMessage() {} + +func (x *Permission) ProtoReflect() protoreflect.Message { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Permission.ProtoReflect.Descriptor instead. +func (*Permission) Descriptor() ([]byte, []int) { + return file_pbauth_v1alpha1_traffic_permissions_proto_rawDescGZIP(), []int{4} +} + +func (x *Permission) GetSources() []*Source { + if x != nil { + return x.Sources + } + return nil +} + +func (x *Permission) GetDestinationRules() []*DestinationRule { + if x != nil { + return x.DestinationRules + } + return nil +} + +// Source represents the source identity. +// To specify any of the wildcard sources, the specific fields need to be omitted. +// For example, for a wildcard namespace, identity_name should be omitted. +type Source struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IdentityName string `protobuf:"bytes,1,opt,name=identity_name,json=identityName,proto3" json:"identity_name,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` + Partition string `protobuf:"bytes,3,opt,name=partition,proto3" json:"partition,omitempty"` + Peer string `protobuf:"bytes,4,opt,name=peer,proto3" json:"peer,omitempty"` + SamenessGroup string `protobuf:"bytes,5,opt,name=sameness_group,json=samenessGroup,proto3" json:"sameness_group,omitempty"` + // exclude is a list of sources to exclude from this source. + Exclude []*ExcludeSource `protobuf:"bytes,6,rep,name=exclude,proto3" json:"exclude,omitempty"` +} + +func (x *Source) Reset() { + *x = Source{} + if protoimpl.UnsafeEnabled { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Source) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Source) ProtoMessage() {} + +func (x *Source) ProtoReflect() protoreflect.Message { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Source.ProtoReflect.Descriptor instead. +func (*Source) Descriptor() ([]byte, []int) { + return file_pbauth_v1alpha1_traffic_permissions_proto_rawDescGZIP(), []int{5} +} + +func (x *Source) GetIdentityName() string { + if x != nil { + return x.IdentityName + } + return "" +} + +func (x *Source) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *Source) GetPartition() string { + if x != nil { + return x.Partition + } + return "" +} + +func (x *Source) GetPeer() string { + if x != nil { + return x.Peer + } + return "" +} + +func (x *Source) GetSamenessGroup() string { + if x != nil { + return x.SamenessGroup + } + return "" +} + +func (x *Source) GetExclude() []*ExcludeSource { + if x != nil { + return x.Exclude + } + return nil +} + +// ExcludeSource is almost the same as source but it prevents the addition of +// matchiing sources. +type ExcludeSource struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IdentityName string `protobuf:"bytes,1,opt,name=identity_name,json=identityName,proto3" json:"identity_name,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` + Partition string `protobuf:"bytes,3,opt,name=partition,proto3" json:"partition,omitempty"` + Peer string `protobuf:"bytes,4,opt,name=peer,proto3" json:"peer,omitempty"` + SamenessGroup string `protobuf:"bytes,5,opt,name=sameness_group,json=samenessGroup,proto3" json:"sameness_group,omitempty"` +} + +func (x *ExcludeSource) Reset() { + *x = ExcludeSource{} + if protoimpl.UnsafeEnabled { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExcludeSource) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExcludeSource) ProtoMessage() {} + +func (x *ExcludeSource) ProtoReflect() protoreflect.Message { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExcludeSource.ProtoReflect.Descriptor instead. +func (*ExcludeSource) Descriptor() ([]byte, []int) { + return file_pbauth_v1alpha1_traffic_permissions_proto_rawDescGZIP(), []int{6} +} + +func (x *ExcludeSource) GetIdentityName() string { + if x != nil { + return x.IdentityName + } + return "" +} + +func (x *ExcludeSource) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *ExcludeSource) GetPartition() string { + if x != nil { + return x.Partition + } + return "" +} + +func (x *ExcludeSource) GetPeer() string { + if x != nil { + return x.Peer + } + return "" +} + +func (x *ExcludeSource) GetSamenessGroup() string { + if x != nil { + return x.SamenessGroup + } + return "" +} + +// DestinationRule contains rules rules to apply to the incoming connection. +type DestinationRule struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PathExact string `protobuf:"bytes,1,opt,name=path_exact,json=pathExact,proto3" json:"path_exact,omitempty"` + PathPrefix string `protobuf:"bytes,2,opt,name=path_prefix,json=pathPrefix,proto3" json:"path_prefix,omitempty"` + PathRegex string `protobuf:"bytes,3,opt,name=path_regex,json=pathRegex,proto3" json:"path_regex,omitempty"` + // methods is the list of HTTP methods. If no methods are specified, + // this rule will apply to all methods. + Methods []string `protobuf:"bytes,4,rep,name=methods,proto3" json:"methods,omitempty"` + Header *DestinationRuleHeader `protobuf:"bytes,5,opt,name=header,proto3" json:"header,omitempty"` + PortNames []string `protobuf:"bytes,6,rep,name=port_names,json=portNames,proto3" json:"port_names,omitempty"` + // exclude contains a list of rules to exclude when evaluating rules for the incoming connection. + Exclude []*ExcludePermissionRule `protobuf:"bytes,7,rep,name=exclude,proto3" json:"exclude,omitempty"` +} + +func (x *DestinationRule) Reset() { + *x = DestinationRule{} + if protoimpl.UnsafeEnabled { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DestinationRule) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DestinationRule) ProtoMessage() {} + +func (x *DestinationRule) ProtoReflect() protoreflect.Message { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DestinationRule.ProtoReflect.Descriptor instead. +func (*DestinationRule) Descriptor() ([]byte, []int) { + return file_pbauth_v1alpha1_traffic_permissions_proto_rawDescGZIP(), []int{7} +} + +func (x *DestinationRule) GetPathExact() string { + if x != nil { + return x.PathExact + } + return "" +} + +func (x *DestinationRule) GetPathPrefix() string { + if x != nil { + return x.PathPrefix + } + return "" +} + +func (x *DestinationRule) GetPathRegex() string { + if x != nil { + return x.PathRegex + } + return "" +} + +func (x *DestinationRule) GetMethods() []string { + if x != nil { + return x.Methods + } + return nil +} + +func (x *DestinationRule) GetHeader() *DestinationRuleHeader { + if x != nil { + return x.Header + } + return nil +} + +func (x *DestinationRule) GetPortNames() []string { + if x != nil { + return x.PortNames + } + return nil +} + +func (x *DestinationRule) GetExclude() []*ExcludePermissionRule { + if x != nil { + return x.Exclude + } + return nil +} + +type ExcludePermissionRule struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PathExact string `protobuf:"bytes,1,opt,name=path_exact,json=pathExact,proto3" json:"path_exact,omitempty"` + PathPrefix string `protobuf:"bytes,2,opt,name=path_prefix,json=pathPrefix,proto3" json:"path_prefix,omitempty"` + PathRegex string `protobuf:"bytes,3,opt,name=path_regex,json=pathRegex,proto3" json:"path_regex,omitempty"` + // methods is the list of HTTP methods. + Methods []string `protobuf:"bytes,4,rep,name=methods,proto3" json:"methods,omitempty"` + Header *DestinationRuleHeader `protobuf:"bytes,5,opt,name=header,proto3" json:"header,omitempty"` + // port_names is a list of workload ports to apply this rule to. The ports specified here + // must be the ports used in the connection. + PortNames []string `protobuf:"bytes,6,rep,name=port_names,json=portNames,proto3" json:"port_names,omitempty"` +} + +func (x *ExcludePermissionRule) Reset() { + *x = ExcludePermissionRule{} + if protoimpl.UnsafeEnabled { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExcludePermissionRule) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExcludePermissionRule) ProtoMessage() {} + +func (x *ExcludePermissionRule) ProtoReflect() protoreflect.Message { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExcludePermissionRule.ProtoReflect.Descriptor instead. +func (*ExcludePermissionRule) Descriptor() ([]byte, []int) { + return file_pbauth_v1alpha1_traffic_permissions_proto_rawDescGZIP(), []int{8} +} + +func (x *ExcludePermissionRule) GetPathExact() string { + if x != nil { + return x.PathExact + } + return "" +} + +func (x *ExcludePermissionRule) GetPathPrefix() string { + if x != nil { + return x.PathPrefix + } + return "" +} + +func (x *ExcludePermissionRule) GetPathRegex() string { + if x != nil { + return x.PathRegex + } + return "" +} + +func (x *ExcludePermissionRule) GetMethods() []string { + if x != nil { + return x.Methods + } + return nil +} + +func (x *ExcludePermissionRule) GetHeader() *DestinationRuleHeader { + if x != nil { + return x.Header + } + return nil +} + +func (x *ExcludePermissionRule) GetPortNames() []string { + if x != nil { + return x.PortNames + } + return nil +} + +type DestinationRuleHeader struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Present bool `protobuf:"varint,2,opt,name=present,proto3" json:"present,omitempty"` + Exact string `protobuf:"bytes,3,opt,name=exact,proto3" json:"exact,omitempty"` + Prefix string `protobuf:"bytes,4,opt,name=prefix,proto3" json:"prefix,omitempty"` + Suffix string `protobuf:"bytes,5,opt,name=suffix,proto3" json:"suffix,omitempty"` + Regex string `protobuf:"bytes,6,opt,name=regex,proto3" json:"regex,omitempty"` + Invert bool `protobuf:"varint,7,opt,name=invert,proto3" json:"invert,omitempty"` +} + +func (x *DestinationRuleHeader) Reset() { + *x = DestinationRuleHeader{} + if protoimpl.UnsafeEnabled { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DestinationRuleHeader) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DestinationRuleHeader) ProtoMessage() {} + +func (x *DestinationRuleHeader) ProtoReflect() protoreflect.Message { + mi := &file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DestinationRuleHeader.ProtoReflect.Descriptor instead. +func (*DestinationRuleHeader) Descriptor() ([]byte, []int) { + return file_pbauth_v1alpha1_traffic_permissions_proto_rawDescGZIP(), []int{9} +} + +func (x *DestinationRuleHeader) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *DestinationRuleHeader) GetPresent() bool { + if x != nil { + return x.Present + } + return false +} + +func (x *DestinationRuleHeader) GetExact() string { + if x != nil { + return x.Exact + } + return "" +} + +func (x *DestinationRuleHeader) GetPrefix() string { + if x != nil { + return x.Prefix + } + return "" +} + +func (x *DestinationRuleHeader) GetSuffix() string { + if x != nil { + return x.Suffix + } + return "" +} + +func (x *DestinationRuleHeader) GetRegex() string { + if x != nil { + return x.Regex + } + return "" +} + +func (x *DestinationRuleHeader) GetInvert() bool { + if x != nil { + return x.Invert + } + return false +} + +var File_pbauth_v1alpha1_traffic_permissions_proto protoreflect.FileDescriptor + +var file_pbauth_v1alpha1_traffic_permissions_proto_rawDesc = []byte{ + 0x0a, 0x29, 0x70, 0x62, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x22, 0xf1, 0x01, 0x0a, 0x12, + 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x4d, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x3e, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x26, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x4c, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, + 0xab, 0x01, 0x0a, 0x1b, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, + 0x66, 0x66, 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x3e, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x26, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x4c, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xab, 0x01, + 0x0a, 0x1b, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x66, 0x66, + 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3e, 0x0a, + 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4c, 0x0a, + 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, + 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x5b, 0x0a, 0x0b, 0x44, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x27, 0x0a, 0x0f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0xac, 0x01, 0x0a, 0x0a, 0x50, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x5c, 0x0a, 0x11, 0x64, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x22, 0xed, 0x01, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x61, 0x6d, 0x65, 0x6e, + 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x73, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x47, + 0x0a, 0x07, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x07, + 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x22, 0xab, 0x01, 0x0a, 0x0d, 0x45, 0x78, 0x63, 0x6c, + 0x75, 0x64, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x65, + 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x12, 0x25, + 0x0a, 0x0e, 0x73, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0xc9, 0x02, 0x0a, 0x0f, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x74, + 0x68, 0x5f, 0x65, 0x78, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, + 0x61, 0x74, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x74, 0x68, + 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, + 0x61, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x74, + 0x68, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, + 0x61, 0x74, 0x68, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x68, 0x6f, + 0x64, 0x73, 0x12, 0x4d, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x75, 0x6c, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, + 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x12, 0x4f, 0x0a, 0x07, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x07, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, + 0x65, 0x22, 0xfe, 0x01, 0x0a, 0x15, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, + 0x61, 0x74, 0x68, 0x5f, 0x65, 0x78, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x70, 0x61, 0x74, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, + 0x74, 0x68, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x70, 0x61, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x70, + 0x61, 0x74, 0x68, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x70, 0x61, 0x74, 0x68, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x74, + 0x68, 0x6f, 0x64, 0x73, 0x12, 0x4d, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x22, 0xb9, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x78, + 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x78, 0x61, 0x63, 0x74, + 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x75, 0x66, 0x66, + 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, + 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x2a, 0x43, + 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x43, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x4e, 0x59, 0x10, + 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, + 0x57, 0x10, 0x02, 0x42, 0x9f, 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x17, 0x54, 0x72, 0x61, 0x66, + 0x66, 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, + 0x61, 0x75, 0x74, 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, + 0x43, 0x41, 0xaa, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0xca, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0xea, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x41, 0x75, 0x74, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pbauth_v1alpha1_traffic_permissions_proto_rawDescOnce sync.Once + file_pbauth_v1alpha1_traffic_permissions_proto_rawDescData = file_pbauth_v1alpha1_traffic_permissions_proto_rawDesc +) + +func file_pbauth_v1alpha1_traffic_permissions_proto_rawDescGZIP() []byte { + file_pbauth_v1alpha1_traffic_permissions_proto_rawDescOnce.Do(func() { + file_pbauth_v1alpha1_traffic_permissions_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbauth_v1alpha1_traffic_permissions_proto_rawDescData) + }) + return file_pbauth_v1alpha1_traffic_permissions_proto_rawDescData +} + +var file_pbauth_v1alpha1_traffic_permissions_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_pbauth_v1alpha1_traffic_permissions_proto_goTypes = []interface{}{ + (Action)(0), // 0: hashicorp.consul.auth.v1alpha1.Action + (*TrafficPermissions)(nil), // 1: hashicorp.consul.auth.v1alpha1.TrafficPermissions + (*NamespaceTrafficPermissions)(nil), // 2: hashicorp.consul.auth.v1alpha1.NamespaceTrafficPermissions + (*PartitionTrafficPermissions)(nil), // 3: hashicorp.consul.auth.v1alpha1.PartitionTrafficPermissions + (*Destination)(nil), // 4: hashicorp.consul.auth.v1alpha1.Destination + (*Permission)(nil), // 5: hashicorp.consul.auth.v1alpha1.Permission + (*Source)(nil), // 6: hashicorp.consul.auth.v1alpha1.Source + (*ExcludeSource)(nil), // 7: hashicorp.consul.auth.v1alpha1.ExcludeSource + (*DestinationRule)(nil), // 8: hashicorp.consul.auth.v1alpha1.DestinationRule + (*ExcludePermissionRule)(nil), // 9: hashicorp.consul.auth.v1alpha1.ExcludePermissionRule + (*DestinationRuleHeader)(nil), // 10: hashicorp.consul.auth.v1alpha1.DestinationRuleHeader +} +var file_pbauth_v1alpha1_traffic_permissions_proto_depIdxs = []int32{ + 4, // 0: hashicorp.consul.auth.v1alpha1.TrafficPermissions.destination:type_name -> hashicorp.consul.auth.v1alpha1.Destination + 0, // 1: hashicorp.consul.auth.v1alpha1.TrafficPermissions.action:type_name -> hashicorp.consul.auth.v1alpha1.Action + 5, // 2: hashicorp.consul.auth.v1alpha1.TrafficPermissions.permissions:type_name -> hashicorp.consul.auth.v1alpha1.Permission + 0, // 3: hashicorp.consul.auth.v1alpha1.NamespaceTrafficPermissions.action:type_name -> hashicorp.consul.auth.v1alpha1.Action + 5, // 4: hashicorp.consul.auth.v1alpha1.NamespaceTrafficPermissions.permissions:type_name -> hashicorp.consul.auth.v1alpha1.Permission + 0, // 5: hashicorp.consul.auth.v1alpha1.PartitionTrafficPermissions.action:type_name -> hashicorp.consul.auth.v1alpha1.Action + 5, // 6: hashicorp.consul.auth.v1alpha1.PartitionTrafficPermissions.permissions:type_name -> hashicorp.consul.auth.v1alpha1.Permission + 6, // 7: hashicorp.consul.auth.v1alpha1.Permission.sources:type_name -> hashicorp.consul.auth.v1alpha1.Source + 8, // 8: hashicorp.consul.auth.v1alpha1.Permission.destination_rules:type_name -> hashicorp.consul.auth.v1alpha1.DestinationRule + 7, // 9: hashicorp.consul.auth.v1alpha1.Source.exclude:type_name -> hashicorp.consul.auth.v1alpha1.ExcludeSource + 10, // 10: hashicorp.consul.auth.v1alpha1.DestinationRule.header:type_name -> hashicorp.consul.auth.v1alpha1.DestinationRuleHeader + 9, // 11: hashicorp.consul.auth.v1alpha1.DestinationRule.exclude:type_name -> hashicorp.consul.auth.v1alpha1.ExcludePermissionRule + 10, // 12: hashicorp.consul.auth.v1alpha1.ExcludePermissionRule.header:type_name -> hashicorp.consul.auth.v1alpha1.DestinationRuleHeader + 13, // [13:13] is the sub-list for method output_type + 13, // [13:13] is the sub-list for method input_type + 13, // [13:13] is the sub-list for extension type_name + 13, // [13:13] is the sub-list for extension extendee + 0, // [0:13] is the sub-list for field type_name +} + +func init() { file_pbauth_v1alpha1_traffic_permissions_proto_init() } +func file_pbauth_v1alpha1_traffic_permissions_proto_init() { + if File_pbauth_v1alpha1_traffic_permissions_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TrafficPermissions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NamespaceTrafficPermissions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PartitionTrafficPermissions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Destination); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Permission); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Source); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExcludeSource); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DestinationRule); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExcludePermissionRule); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DestinationRuleHeader); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pbauth_v1alpha1_traffic_permissions_proto_rawDesc, + NumEnums: 1, + NumMessages: 10, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pbauth_v1alpha1_traffic_permissions_proto_goTypes, + DependencyIndexes: file_pbauth_v1alpha1_traffic_permissions_proto_depIdxs, + EnumInfos: file_pbauth_v1alpha1_traffic_permissions_proto_enumTypes, + MessageInfos: file_pbauth_v1alpha1_traffic_permissions_proto_msgTypes, + }.Build() + File_pbauth_v1alpha1_traffic_permissions_proto = out.File + file_pbauth_v1alpha1_traffic_permissions_proto_rawDesc = nil + file_pbauth_v1alpha1_traffic_permissions_proto_goTypes = nil + file_pbauth_v1alpha1_traffic_permissions_proto_depIdxs = nil +} diff --git a/proto-public/pbauth/v1alpha1/traffic_permissions.proto b/proto-public/pbauth/v1alpha1/traffic_permissions.proto new file mode 100644 index 000000000000..5567a70a6b78 --- /dev/null +++ b/proto-public/pbauth/v1alpha1/traffic_permissions.proto @@ -0,0 +1,124 @@ +syntax = "proto3"; + +package hashicorp.consul.auth.v1alpha1; + +message TrafficPermissions { + // destination is a configuration of the destination proxies + // where these traffic permissions should apply. + Destination destination = 1; + + // Action can be either allow or deny for the entire object. It will default to allow. + // + // If action is allow, + // we will allow the connection if one of the rules in Rules matches, in other words, we will deny + // all requests except for the ones that match Rules. If Consul is in default allow mode, then allow + // actions have no effect without a deny permission as everything is allowed by default. + // + // If action is deny, + // we will deny the connection if one of the rules in Rules match, in other words, + // we will allow all requests except for the ones that match Rules. If Consul is default deny mode, + // then deny permissions have no effect without an allow permission as everything is denied by default. + // + // Action unspecified is reserved for compatibility with the addition of future actions. + Action action = 2; + + // permissions is a list of permissions to match on. + // They are applied using OR semantics. + repeated Permission permissions = 3; +} + +message NamespaceTrafficPermissions { + Action action = 1; + repeated Permission permissions = 2; +} + +message PartitionTrafficPermissions { + Action action = 1; + repeated Permission permissions = 2; +} + +// Destination contains the name or name-prefix of the WorkloadIdentity. +// The WorkloadIdentity resource must +// be in the same tenancy as the TrafficPermissions resource. +message Destination { + string identity_name = 1; + string identity_prefix = 2; +} + +enum Action { + ACTION_UNSPECIFIED = 0; + ACTION_DENY = 1; + ACTION_ALLOW = 2; +} + +// permissions is a list of permissions to match on. +message Permission { + // sources is a list of sources in this traffic permission. + repeated Source sources = 1; + // destination_rules is a list of rules to apply for matching sources in this Permission. + // These rules are specific to the request or connection that is going to the destination(s) + // selected by the TrafficPermissions resource. + repeated DestinationRule destination_rules = 2; +} + +// Source represents the source identity. +// To specify any of the wildcard sources, the specific fields need to be omitted. +// For example, for a wildcard namespace, identity_name should be omitted. +message Source { + string identity_name = 1; + string namespace = 2; + string partition = 3; + string peer = 4; + string sameness_group = 5; + + // exclude is a list of sources to exclude from this source. + repeated ExcludeSource exclude = 6; +} + +// ExcludeSource is almost the same as source but it prevents the addition of +// matchiing sources. +message ExcludeSource { + string identity_name = 1; + string namespace = 2; + string partition = 3; + string peer = 4; + string sameness_group = 5; +} + +// DestinationRule contains rules rules to apply to the incoming connection. +message DestinationRule { + string path_exact = 1; + string path_prefix = 2; + string path_regex = 3; + // methods is the list of HTTP methods. If no methods are specified, + // this rule will apply to all methods. + repeated string methods = 4; + DestinationRuleHeader header = 5; + repeated string port_names = 6; + // exclude contains a list of rules to exclude when evaluating rules for the incoming connection. + repeated ExcludePermissionRule exclude = 7; +} + +message ExcludePermissionRule { + string path_exact = 1; + string path_prefix = 2; + string path_regex = 3; + // methods is the list of HTTP methods. + repeated string methods = 4; + + DestinationRuleHeader header = 5; + + // port_names is a list of workload ports to apply this rule to. The ports specified here + // must be the ports used in the connection. + repeated string port_names = 6; +} + +message DestinationRuleHeader { + string name = 1; + bool present = 2; + string exact = 3; + string prefix = 4; + string suffix = 5; + string regex = 6; + bool invert = 7; +} diff --git a/proto-public/pbauth/v1alpha1/workload_identity.pb.binary.go b/proto-public/pbauth/v1alpha1/workload_identity.pb.binary.go new file mode 100644 index 000000000000..1e17c55b0d64 --- /dev/null +++ b/proto-public/pbauth/v1alpha1/workload_identity.pb.binary.go @@ -0,0 +1,18 @@ +// Code generated by protoc-gen-go-binary. DO NOT EDIT. +// source: pbauth/v1alpha1/workload_identity.proto + +package authv1alpha1 + +import ( + "google.golang.org/protobuf/proto" +) + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *WorkloadIdentity) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *WorkloadIdentity) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} diff --git a/proto-public/pbauth/v1alpha1/workload_identity.pb.go b/proto-public/pbauth/v1alpha1/workload_identity.pb.go new file mode 100644 index 000000000000..854ef97cc513 --- /dev/null +++ b/proto-public/pbauth/v1alpha1/workload_identity.pb.go @@ -0,0 +1,152 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc (unknown) +// source: pbauth/v1alpha1/workload_identity.proto + +package authv1alpha1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type WorkloadIdentity struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *WorkloadIdentity) Reset() { + *x = WorkloadIdentity{} + if protoimpl.UnsafeEnabled { + mi := &file_pbauth_v1alpha1_workload_identity_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WorkloadIdentity) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WorkloadIdentity) ProtoMessage() {} + +func (x *WorkloadIdentity) ProtoReflect() protoreflect.Message { + mi := &file_pbauth_v1alpha1_workload_identity_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WorkloadIdentity.ProtoReflect.Descriptor instead. +func (*WorkloadIdentity) Descriptor() ([]byte, []int) { + return file_pbauth_v1alpha1_workload_identity_proto_rawDescGZIP(), []int{0} +} + +var File_pbauth_v1alpha1_workload_identity_proto protoreflect.FileDescriptor + +var file_pbauth_v1alpha1_workload_identity_proto_rawDesc = []byte{ + 0x0a, 0x27, 0x70, 0x62, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x22, 0x12, 0x0a, 0x10, 0x57, 0x6f, 0x72, + 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x42, 0x9d, 0x02, + 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x42, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x61, 0x75, 0x74, 0x68, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x41, 0xaa, 0x02, 0x1e, 0x48, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x41, 0x75, + 0x74, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x1e, 0x48, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x41, + 0x75, 0x74, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2a, 0x48, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, + 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, + 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x41, + 0x75, 0x74, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pbauth_v1alpha1_workload_identity_proto_rawDescOnce sync.Once + file_pbauth_v1alpha1_workload_identity_proto_rawDescData = file_pbauth_v1alpha1_workload_identity_proto_rawDesc +) + +func file_pbauth_v1alpha1_workload_identity_proto_rawDescGZIP() []byte { + file_pbauth_v1alpha1_workload_identity_proto_rawDescOnce.Do(func() { + file_pbauth_v1alpha1_workload_identity_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbauth_v1alpha1_workload_identity_proto_rawDescData) + }) + return file_pbauth_v1alpha1_workload_identity_proto_rawDescData +} + +var file_pbauth_v1alpha1_workload_identity_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_pbauth_v1alpha1_workload_identity_proto_goTypes = []interface{}{ + (*WorkloadIdentity)(nil), // 0: hashicorp.consul.auth.v1alpha1.WorkloadIdentity +} +var file_pbauth_v1alpha1_workload_identity_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_pbauth_v1alpha1_workload_identity_proto_init() } +func file_pbauth_v1alpha1_workload_identity_proto_init() { + if File_pbauth_v1alpha1_workload_identity_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pbauth_v1alpha1_workload_identity_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WorkloadIdentity); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pbauth_v1alpha1_workload_identity_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pbauth_v1alpha1_workload_identity_proto_goTypes, + DependencyIndexes: file_pbauth_v1alpha1_workload_identity_proto_depIdxs, + MessageInfos: file_pbauth_v1alpha1_workload_identity_proto_msgTypes, + }.Build() + File_pbauth_v1alpha1_workload_identity_proto = out.File + file_pbauth_v1alpha1_workload_identity_proto_rawDesc = nil + file_pbauth_v1alpha1_workload_identity_proto_goTypes = nil + file_pbauth_v1alpha1_workload_identity_proto_depIdxs = nil +} diff --git a/proto-public/pbauth/v1alpha1/workload_identity.proto b/proto-public/pbauth/v1alpha1/workload_identity.proto new file mode 100644 index 000000000000..7568706931f4 --- /dev/null +++ b/proto-public/pbauth/v1alpha1/workload_identity.proto @@ -0,0 +1,5 @@ +syntax = "proto3"; + +package hashicorp.consul.auth.v1alpha1; + +message WorkloadIdentity {} diff --git a/proto-public/pbmesh/v1alpha1/computed_routes.pb.go b/proto-public/pbmesh/v1alpha1/computed_routes.pb.go index 8b614d20e5aa..59a07d41a57c 100644 --- a/proto-public/pbmesh/v1alpha1/computed_routes.pb.go +++ b/proto-public/pbmesh/v1alpha1/computed_routes.pb.go @@ -11,6 +11,7 @@ package meshv1alpha1 import ( v1alpha1 "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" + pbresource "github.com/hashicorp/consul/proto-public/pbresource" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" @@ -84,8 +85,13 @@ type ComputedPortRoutes struct { // *ComputedPortRoutes_Tcp Config isComputedPortRoutes_Config `protobuf_oneof:"config"` UsingDefaultConfig bool `protobuf:"varint,4,opt,name=using_default_config,json=usingDefaultConfig,proto3" json:"using_default_config,omitempty"` // TODO + ParentRef *ParentReference `protobuf:"bytes,5,opt,name=parent_ref,json=parentRef,proto3" json:"parent_ref,omitempty"` + // Protocol is the ParentRef.Port's protocol. It is based on the value in the + // Service object, but may differ depending upon which xRoutes are actually + // in use. + Protocol v1alpha1.Protocol `protobuf:"varint,6,opt,name=protocol,proto3,enum=hashicorp.consul.catalog.v1alpha1.Protocol" json:"protocol,omitempty"` // map key is an opaque string; like disco chain target name - Targets map[string]*BackendTargetDetails `protobuf:"bytes,5,rep,name=targets,proto3" json:"targets,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Targets map[string]*BackendTargetDetails `protobuf:"bytes,7,rep,name=targets,proto3" json:"targets,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *ComputedPortRoutes) Reset() { @@ -155,6 +161,20 @@ func (x *ComputedPortRoutes) GetUsingDefaultConfig() bool { return false } +func (x *ComputedPortRoutes) GetParentRef() *ParentReference { + if x != nil { + return x.ParentRef + } + return nil +} + +func (x *ComputedPortRoutes) GetProtocol() v1alpha1.Protocol { + if x != nil { + return x.Protocol + } + return v1alpha1.Protocol(0) +} + func (x *ComputedPortRoutes) GetTargets() map[string]*BackendTargetDetails { if x != nil { return x.Targets @@ -189,8 +209,7 @@ type ComputedHTTPRoute struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ParentRef *ParentReference `protobuf:"bytes,1,opt,name=parent_ref,json=parentRef,proto3" json:"parent_ref,omitempty"` - Rules []*ComputedHTTPRouteRule `protobuf:"bytes,3,rep,name=rules,proto3" json:"rules,omitempty"` + Rules []*ComputedHTTPRouteRule `protobuf:"bytes,2,rep,name=rules,proto3" json:"rules,omitempty"` } func (x *ComputedHTTPRoute) Reset() { @@ -225,13 +244,6 @@ func (*ComputedHTTPRoute) Descriptor() ([]byte, []int) { return file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP(), []int{2} } -func (x *ComputedHTTPRoute) GetParentRef() *ParentReference { - if x != nil { - return x.ParentRef - } - return nil -} - func (x *ComputedHTTPRoute) GetRules() []*ComputedHTTPRouteRule { if x != nil { return x.Rules @@ -393,8 +405,7 @@ type ComputedGRPCRoute struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ParentRef *ParentReference `protobuf:"bytes,1,opt,name=parent_ref,json=parentRef,proto3" json:"parent_ref,omitempty"` - Rules []*ComputedGRPCRouteRule `protobuf:"bytes,3,rep,name=rules,proto3" json:"rules,omitempty"` + Rules []*ComputedGRPCRouteRule `protobuf:"bytes,2,rep,name=rules,proto3" json:"rules,omitempty"` } func (x *ComputedGRPCRoute) Reset() { @@ -429,13 +440,6 @@ func (*ComputedGRPCRoute) Descriptor() ([]byte, []int) { return file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP(), []int{5} } -func (x *ComputedGRPCRoute) GetParentRef() *ParentReference { - if x != nil { - return x.ParentRef - } - return nil -} - func (x *ComputedGRPCRoute) GetRules() []*ComputedGRPCRouteRule { if x != nil { return x.Rules @@ -597,8 +601,7 @@ type ComputedTCPRoute struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ParentRef *ParentReference `protobuf:"bytes,1,opt,name=parent_ref,json=parentRef,proto3" json:"parent_ref,omitempty"` - Rules []*ComputedTCPRouteRule `protobuf:"bytes,2,rep,name=rules,proto3" json:"rules,omitempty"` + Rules []*ComputedTCPRouteRule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"` } func (x *ComputedTCPRoute) Reset() { @@ -633,13 +636,6 @@ func (*ComputedTCPRoute) Descriptor() ([]byte, []int) { return file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP(), []int{8} } -func (x *ComputedTCPRoute) GetParentRef() *ParentReference { - if x != nil { - return x.ParentRef - } - return nil -} - func (x *ComputedTCPRoute) GetRules() []*ComputedTCPRouteRule { if x != nil { return x.Rules @@ -765,9 +761,18 @@ type BackendTargetDetails struct { // identity info BackendRef *BackendReference `protobuf:"bytes,1,opt,name=backend_ref,json=backendRef,proto3" json:"backend_ref,omitempty"` - Service *v1alpha1.Service `protobuf:"bytes,3,opt,name=service,proto3" json:"service,omitempty"` - FailoverPolicy *v1alpha1.FailoverPolicy `protobuf:"bytes,4,opt,name=failover_policy,json=failoverPolicy,proto3" json:"failover_policy,omitempty"` - DestinationPolicy *DestinationPolicy `protobuf:"bytes,5,opt,name=destination_policy,json=destinationPolicy,proto3" json:"destination_policy,omitempty"` + MeshPort string `protobuf:"bytes,2,opt,name=mesh_port,json=meshPort,proto3" json:"mesh_port,omitempty"` + FailoverConfig *v1alpha1.FailoverConfig `protobuf:"bytes,3,opt,name=failover_config,json=failoverConfig,proto3" json:"failover_config,omitempty"` + DestinationConfig *DestinationConfig `protobuf:"bytes,4,opt,name=destination_config,json=destinationConfig,proto3" json:"destination_config,omitempty"` + // ServiceEndpointsID is not populated naturally and the field exists only for + // downstream consumers. + ServiceEndpointsId *pbresource.ID `protobuf:"bytes,21,opt,name=service_endpoints_id,json=serviceEndpointsId,proto3" json:"service_endpoints_id,omitempty"` + // ServiceEndpoints is not populated naturally and the field exists only for + // downstream consumers. + ServiceEndpoints *v1alpha1.ServiceEndpoints `protobuf:"bytes,22,opt,name=service_endpoints,json=serviceEndpoints,proto3" json:"service_endpoints,omitempty"` + // IdentityRefs are not populated naturally and the field exists only for + // downstream consumers. + IdentityRefs []*pbresource.Reference `protobuf:"bytes,23,rep,name=identity_refs,json=identityRefs,proto3" json:"identity_refs,omitempty"` } func (x *BackendTargetDetails) Reset() { @@ -809,23 +814,44 @@ func (x *BackendTargetDetails) GetBackendRef() *BackendReference { return nil } -func (x *BackendTargetDetails) GetService() *v1alpha1.Service { +func (x *BackendTargetDetails) GetMeshPort() string { + if x != nil { + return x.MeshPort + } + return "" +} + +func (x *BackendTargetDetails) GetFailoverConfig() *v1alpha1.FailoverConfig { + if x != nil { + return x.FailoverConfig + } + return nil +} + +func (x *BackendTargetDetails) GetDestinationConfig() *DestinationConfig { + if x != nil { + return x.DestinationConfig + } + return nil +} + +func (x *BackendTargetDetails) GetServiceEndpointsId() *pbresource.ID { if x != nil { - return x.Service + return x.ServiceEndpointsId } return nil } -func (x *BackendTargetDetails) GetFailoverPolicy() *v1alpha1.FailoverPolicy { +func (x *BackendTargetDetails) GetServiceEndpoints() *v1alpha1.ServiceEndpoints { if x != nil { - return x.FailoverPolicy + return x.ServiceEndpoints } return nil } -func (x *BackendTargetDetails) GetDestinationPolicy() *DestinationPolicy { +func (x *BackendTargetDetails) GetIdentityRefs() []*pbresource.Reference { if x != nil { - return x.DestinationPolicy + return x.IdentityRefs } return nil } @@ -840,81 +866,90 @@ var file_pbmesh_v1alpha1_computed_routes_proto_rawDesc = []byte{ 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x28, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x20, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x28, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x70, 0x62, 0x6d, - 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x67, 0x72, 0x70, - 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x70, - 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x68, - 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x28, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x70, 0x62, 0x6d, 0x65, 0x73, - 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, - 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf0, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, - 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x68, 0x0a, 0x0e, 0x70, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2e, - 0x50, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x0d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x73, 0x1a, 0x74, 0x0a, 0x12, 0x50, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x48, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, - 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xf5, 0x03, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x70, - 0x75, 0x74, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x47, - 0x0a, 0x04, 0x68, 0x74, 0x74, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, - 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x48, - 0x00, 0x52, 0x04, 0x68, 0x74, 0x74, 0x70, 0x12, 0x47, 0x0a, 0x04, 0x67, 0x72, 0x70, 0x63, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x47, - 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x48, 0x00, 0x52, 0x04, 0x67, 0x72, 0x70, 0x63, - 0x12, 0x44, 0x0a, 0x03, 0x74, 0x63, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, + 0x6f, 0x1a, 0x21, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x1a, 0x1c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x28, + 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, + 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, + 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x70, 0x62, 0x6d, 0x65, + 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, + 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x28, 0x70, 0x62, + 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x68, 0x74, + 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, + 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x1a, 0x19, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf0, 0x01, 0x0a, + 0x0e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, + 0x68, 0x0a, 0x0e, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, + 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x70, 0x6f, 0x72, 0x74, + 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x1a, 0x74, 0x0a, 0x12, 0x50, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x48, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, + 0x8e, 0x05, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x47, 0x0a, 0x04, 0x68, 0x74, 0x74, 0x70, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x48, 0x54, + 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x48, 0x00, 0x52, 0x04, 0x68, 0x74, 0x74, 0x70, 0x12, + 0x47, 0x0a, 0x04, 0x67, 0x72, 0x70, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, - 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x48, - 0x00, 0x52, 0x03, 0x74, 0x63, 0x70, 0x12, 0x30, 0x0a, 0x14, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x5f, - 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x59, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x54, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x73, 0x1a, 0x70, 0x0a, 0x0c, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x48, 0x00, 0x52, 0x04, 0x67, 0x72, 0x70, 0x63, 0x12, 0x44, 0x0a, 0x03, 0x74, 0x63, 0x70, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x54, + 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x48, 0x00, 0x52, 0x03, 0x74, 0x63, 0x70, 0x12, 0x30, + 0x0a, 0x14, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x75, 0x73, + 0x69, 0x6e, 0x67, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x4e, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x54, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, - 0xb6, 0x01, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x48, 0x54, 0x54, 0x50, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4e, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, - 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x09, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x66, 0x12, 0x4b, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, + 0x12, 0x47, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, + 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x59, 0x0a, 0x07, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, + 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, + 0x75, 0x74, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x54, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x73, 0x1a, 0x70, 0x0a, 0x0c, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x54, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x22, 0x66, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x48, 0x54, 0x54, 0x50, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4b, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, - 0x65, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0xa2, 0x03, 0x0a, 0x15, 0x43, 0x6f, 0x6d, + 0x65, 0x73, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0xa2, 0x03, 0x0a, 0x15, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x48, 0x0a, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, @@ -951,120 +986,123 @@ var file_pbmesh_v1alpha1_computed_routes_proto_rawDesc = []byte{ 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x73, 0x22, 0xb6, 0x01, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x47, - 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4e, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x09, 0x70, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x12, 0x4b, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, - 0x64, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, - 0x72, 0x75, 0x6c, 0x65, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0xa2, 0x03, 0x0a, 0x15, - 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x48, 0x0a, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x73, 0x22, 0x66, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x47, 0x52, + 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4b, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, - 0x49, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x59, 0x0a, 0x0c, 0x62, 0x61, - 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x47, 0x52, 0x50, 0x43, 0x42, 0x61, - 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x52, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, - 0x64, 0x52, 0x65, 0x66, 0x73, 0x12, 0x4d, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, + 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, + 0x75, 0x6c, 0x65, 0x73, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0xa2, 0x03, 0x0a, 0x15, 0x43, + 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x52, 0x75, 0x6c, 0x65, 0x12, 0x48, 0x0a, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, - 0x22, 0xa2, 0x01, 0x0a, 0x16, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x47, 0x52, 0x50, - 0x43, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x25, 0x0a, 0x0e, 0x62, - 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x49, 0x0a, 0x07, 0x66, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, - 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0xae, 0x01, 0x0a, 0x10, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, - 0x65, 0x64, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4e, 0x0a, 0x0a, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, - 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x12, 0x4a, 0x0a, 0x05, 0x72, 0x75, - 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x65, 0x64, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, - 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x70, 0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, - 0x65, 0x64, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x58, - 0x0a, 0x0c, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x49, + 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x59, 0x0a, 0x0c, 0x62, 0x61, 0x63, + 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x47, 0x52, 0x50, 0x43, 0x42, 0x61, 0x63, + 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x52, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, + 0x52, 0x65, 0x66, 0x73, 0x12, 0x4d, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x6f, + 0x75, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x54, 0x43, - 0x50, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x52, 0x0b, 0x62, 0x61, 0x63, - 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x73, 0x22, 0x56, 0x0a, 0x15, 0x43, 0x6f, 0x6d, 0x70, - 0x75, 0x74, 0x65, 0x64, 0x54, 0x43, 0x50, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, - 0x66, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x61, 0x63, 0x6b, 0x65, - 0x6e, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x22, 0xed, 0x02, 0x0a, 0x14, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x51, 0x0a, 0x0b, 0x62, 0x61, 0x63, - 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, - 0x52, 0x0a, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x44, 0x0a, 0x07, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x5a, 0x0a, 0x0f, 0x66, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, - 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0e, - 0x66, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x60, - 0x0a, 0x12, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, + 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, + 0xa2, 0x01, 0x0a, 0x16, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x47, 0x52, 0x50, 0x43, + 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x61, + 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x49, 0x0a, 0x07, 0x66, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x11, 0x64, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x42, 0x9b, 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x13, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, - 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, - 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, 0x6d, 0x65, 0x73, 0x68, 0x2f, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1e, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, - 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x1e, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, - 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2a, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, - 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x73, 0x22, 0x5e, 0x0a, 0x10, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, + 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4a, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, + 0x64, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, + 0x75, 0x6c, 0x65, 0x73, 0x22, 0x70, 0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, + 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x58, 0x0a, 0x0c, + 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x54, 0x43, 0x50, 0x42, + 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x52, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, + 0x6e, 0x64, 0x52, 0x65, 0x66, 0x73, 0x22, 0x56, 0x0a, 0x15, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, + 0x65, 0x64, 0x54, 0x43, 0x50, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, + 0x25, 0x0a, 0x0e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0xc8, + 0x04, 0x0a, 0x14, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x51, 0x0a, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, + 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x61, + 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0a, + 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x65, + 0x73, 0x68, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, + 0x65, 0x73, 0x68, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x5a, 0x0a, 0x0f, 0x66, 0x61, 0x69, 0x6c, 0x6f, + 0x76, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x0e, 0x66, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x60, 0x0a, 0x12, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x11, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a, 0x14, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x15, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, + 0x49, 0x44, 0x52, 0x12, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x64, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x73, 0x49, 0x64, 0x12, 0x60, 0x0a, 0x11, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x10, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, + 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x49, 0x0a, 0x0d, 0x69, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x17, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, + 0x65, 0x66, 0x73, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x15, 0x42, 0x9b, 0x02, 0x0a, 0x22, 0x63, 0x6f, + 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x42, 0x13, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, + 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, + 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1081,68 +1119,72 @@ func file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP() []byte { var file_pbmesh_v1alpha1_computed_routes_proto_msgTypes = make([]protoimpl.MessageInfo, 14) var file_pbmesh_v1alpha1_computed_routes_proto_goTypes = []interface{}{ - (*ComputedRoutes)(nil), // 0: hashicorp.consul.mesh.v1alpha1.ComputedRoutes - (*ComputedPortRoutes)(nil), // 1: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes - (*ComputedHTTPRoute)(nil), // 2: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRoute - (*ComputedHTTPRouteRule)(nil), // 3: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRouteRule - (*ComputedHTTPBackendRef)(nil), // 4: hashicorp.consul.mesh.v1alpha1.ComputedHTTPBackendRef - (*ComputedGRPCRoute)(nil), // 5: hashicorp.consul.mesh.v1alpha1.ComputedGRPCRoute - (*ComputedGRPCRouteRule)(nil), // 6: hashicorp.consul.mesh.v1alpha1.ComputedGRPCRouteRule - (*ComputedGRPCBackendRef)(nil), // 7: hashicorp.consul.mesh.v1alpha1.ComputedGRPCBackendRef - (*ComputedTCPRoute)(nil), // 8: hashicorp.consul.mesh.v1alpha1.ComputedTCPRoute - (*ComputedTCPRouteRule)(nil), // 9: hashicorp.consul.mesh.v1alpha1.ComputedTCPRouteRule - (*ComputedTCPBackendRef)(nil), // 10: hashicorp.consul.mesh.v1alpha1.ComputedTCPBackendRef - (*BackendTargetDetails)(nil), // 11: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails - nil, // 12: hashicorp.consul.mesh.v1alpha1.ComputedRoutes.PortedConfigsEntry - nil, // 13: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.TargetsEntry - (*ParentReference)(nil), // 14: hashicorp.consul.mesh.v1alpha1.ParentReference - (*HTTPRouteMatch)(nil), // 15: hashicorp.consul.mesh.v1alpha1.HTTPRouteMatch - (*HTTPRouteFilter)(nil), // 16: hashicorp.consul.mesh.v1alpha1.HTTPRouteFilter - (*HTTPRouteTimeouts)(nil), // 17: hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts - (*HTTPRouteRetries)(nil), // 18: hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries - (*GRPCRouteMatch)(nil), // 19: hashicorp.consul.mesh.v1alpha1.GRPCRouteMatch - (*GRPCRouteFilter)(nil), // 20: hashicorp.consul.mesh.v1alpha1.GRPCRouteFilter - (*BackendReference)(nil), // 21: hashicorp.consul.mesh.v1alpha1.BackendReference - (*v1alpha1.Service)(nil), // 22: hashicorp.consul.catalog.v1alpha1.Service - (*v1alpha1.FailoverPolicy)(nil), // 23: hashicorp.consul.catalog.v1alpha1.FailoverPolicy - (*DestinationPolicy)(nil), // 24: hashicorp.consul.mesh.v1alpha1.DestinationPolicy + (*ComputedRoutes)(nil), // 0: hashicorp.consul.mesh.v1alpha1.ComputedRoutes + (*ComputedPortRoutes)(nil), // 1: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes + (*ComputedHTTPRoute)(nil), // 2: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRoute + (*ComputedHTTPRouteRule)(nil), // 3: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRouteRule + (*ComputedHTTPBackendRef)(nil), // 4: hashicorp.consul.mesh.v1alpha1.ComputedHTTPBackendRef + (*ComputedGRPCRoute)(nil), // 5: hashicorp.consul.mesh.v1alpha1.ComputedGRPCRoute + (*ComputedGRPCRouteRule)(nil), // 6: hashicorp.consul.mesh.v1alpha1.ComputedGRPCRouteRule + (*ComputedGRPCBackendRef)(nil), // 7: hashicorp.consul.mesh.v1alpha1.ComputedGRPCBackendRef + (*ComputedTCPRoute)(nil), // 8: hashicorp.consul.mesh.v1alpha1.ComputedTCPRoute + (*ComputedTCPRouteRule)(nil), // 9: hashicorp.consul.mesh.v1alpha1.ComputedTCPRouteRule + (*ComputedTCPBackendRef)(nil), // 10: hashicorp.consul.mesh.v1alpha1.ComputedTCPBackendRef + (*BackendTargetDetails)(nil), // 11: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails + nil, // 12: hashicorp.consul.mesh.v1alpha1.ComputedRoutes.PortedConfigsEntry + nil, // 13: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.TargetsEntry + (*ParentReference)(nil), // 14: hashicorp.consul.mesh.v1alpha1.ParentReference + (v1alpha1.Protocol)(0), // 15: hashicorp.consul.catalog.v1alpha1.Protocol + (*HTTPRouteMatch)(nil), // 16: hashicorp.consul.mesh.v1alpha1.HTTPRouteMatch + (*HTTPRouteFilter)(nil), // 17: hashicorp.consul.mesh.v1alpha1.HTTPRouteFilter + (*HTTPRouteTimeouts)(nil), // 18: hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts + (*HTTPRouteRetries)(nil), // 19: hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries + (*GRPCRouteMatch)(nil), // 20: hashicorp.consul.mesh.v1alpha1.GRPCRouteMatch + (*GRPCRouteFilter)(nil), // 21: hashicorp.consul.mesh.v1alpha1.GRPCRouteFilter + (*BackendReference)(nil), // 22: hashicorp.consul.mesh.v1alpha1.BackendReference + (*v1alpha1.FailoverConfig)(nil), // 23: hashicorp.consul.catalog.v1alpha1.FailoverConfig + (*DestinationConfig)(nil), // 24: hashicorp.consul.mesh.v1alpha1.DestinationConfig + (*pbresource.ID)(nil), // 25: hashicorp.consul.resource.ID + (*v1alpha1.ServiceEndpoints)(nil), // 26: hashicorp.consul.catalog.v1alpha1.ServiceEndpoints + (*pbresource.Reference)(nil), // 27: hashicorp.consul.resource.Reference } var file_pbmesh_v1alpha1_computed_routes_proto_depIdxs = []int32{ 12, // 0: hashicorp.consul.mesh.v1alpha1.ComputedRoutes.ported_configs:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedRoutes.PortedConfigsEntry 2, // 1: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.http:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedHTTPRoute 5, // 2: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.grpc:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedGRPCRoute 8, // 3: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.tcp:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedTCPRoute - 13, // 4: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.targets:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.TargetsEntry - 14, // 5: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRoute.parent_ref:type_name -> hashicorp.consul.mesh.v1alpha1.ParentReference - 3, // 6: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRoute.rules:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedHTTPRouteRule - 15, // 7: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRouteRule.matches:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteMatch - 16, // 8: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRouteRule.filters:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteFilter - 4, // 9: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedHTTPBackendRef - 17, // 10: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRouteRule.timeouts:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts - 18, // 11: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRouteRule.retries:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries - 16, // 12: hashicorp.consul.mesh.v1alpha1.ComputedHTTPBackendRef.filters:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteFilter - 14, // 13: hashicorp.consul.mesh.v1alpha1.ComputedGRPCRoute.parent_ref:type_name -> hashicorp.consul.mesh.v1alpha1.ParentReference + 14, // 4: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.parent_ref:type_name -> hashicorp.consul.mesh.v1alpha1.ParentReference + 15, // 5: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.protocol:type_name -> hashicorp.consul.catalog.v1alpha1.Protocol + 13, // 6: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.targets:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.TargetsEntry + 3, // 7: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRoute.rules:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedHTTPRouteRule + 16, // 8: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRouteRule.matches:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteMatch + 17, // 9: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRouteRule.filters:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteFilter + 4, // 10: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedHTTPBackendRef + 18, // 11: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRouteRule.timeouts:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts + 19, // 12: hashicorp.consul.mesh.v1alpha1.ComputedHTTPRouteRule.retries:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries + 17, // 13: hashicorp.consul.mesh.v1alpha1.ComputedHTTPBackendRef.filters:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteFilter 6, // 14: hashicorp.consul.mesh.v1alpha1.ComputedGRPCRoute.rules:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedGRPCRouteRule - 19, // 15: hashicorp.consul.mesh.v1alpha1.ComputedGRPCRouteRule.matches:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCRouteMatch - 20, // 16: hashicorp.consul.mesh.v1alpha1.ComputedGRPCRouteRule.filters:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCRouteFilter + 20, // 15: hashicorp.consul.mesh.v1alpha1.ComputedGRPCRouteRule.matches:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCRouteMatch + 21, // 16: hashicorp.consul.mesh.v1alpha1.ComputedGRPCRouteRule.filters:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCRouteFilter 7, // 17: hashicorp.consul.mesh.v1alpha1.ComputedGRPCRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedGRPCBackendRef - 17, // 18: hashicorp.consul.mesh.v1alpha1.ComputedGRPCRouteRule.timeouts:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts - 18, // 19: hashicorp.consul.mesh.v1alpha1.ComputedGRPCRouteRule.retries:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries - 20, // 20: hashicorp.consul.mesh.v1alpha1.ComputedGRPCBackendRef.filters:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCRouteFilter - 14, // 21: hashicorp.consul.mesh.v1alpha1.ComputedTCPRoute.parent_ref:type_name -> hashicorp.consul.mesh.v1alpha1.ParentReference - 9, // 22: hashicorp.consul.mesh.v1alpha1.ComputedTCPRoute.rules:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedTCPRouteRule - 10, // 23: hashicorp.consul.mesh.v1alpha1.ComputedTCPRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedTCPBackendRef - 21, // 24: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails.backend_ref:type_name -> hashicorp.consul.mesh.v1alpha1.BackendReference - 22, // 25: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails.service:type_name -> hashicorp.consul.catalog.v1alpha1.Service - 23, // 26: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails.failover_policy:type_name -> hashicorp.consul.catalog.v1alpha1.FailoverPolicy - 24, // 27: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails.destination_policy:type_name -> hashicorp.consul.mesh.v1alpha1.DestinationPolicy - 1, // 28: hashicorp.consul.mesh.v1alpha1.ComputedRoutes.PortedConfigsEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes - 11, // 29: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.TargetsEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.BackendTargetDetails - 30, // [30:30] is the sub-list for method output_type - 30, // [30:30] is the sub-list for method input_type - 30, // [30:30] is the sub-list for extension type_name - 30, // [30:30] is the sub-list for extension extendee - 0, // [0:30] is the sub-list for field type_name + 18, // 18: hashicorp.consul.mesh.v1alpha1.ComputedGRPCRouteRule.timeouts:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts + 19, // 19: hashicorp.consul.mesh.v1alpha1.ComputedGRPCRouteRule.retries:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries + 21, // 20: hashicorp.consul.mesh.v1alpha1.ComputedGRPCBackendRef.filters:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCRouteFilter + 9, // 21: hashicorp.consul.mesh.v1alpha1.ComputedTCPRoute.rules:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedTCPRouteRule + 10, // 22: hashicorp.consul.mesh.v1alpha1.ComputedTCPRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedTCPBackendRef + 22, // 23: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails.backend_ref:type_name -> hashicorp.consul.mesh.v1alpha1.BackendReference + 23, // 24: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails.failover_config:type_name -> hashicorp.consul.catalog.v1alpha1.FailoverConfig + 24, // 25: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails.destination_config:type_name -> hashicorp.consul.mesh.v1alpha1.DestinationConfig + 25, // 26: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails.service_endpoints_id:type_name -> hashicorp.consul.resource.ID + 26, // 27: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails.service_endpoints:type_name -> hashicorp.consul.catalog.v1alpha1.ServiceEndpoints + 27, // 28: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails.identity_refs:type_name -> hashicorp.consul.resource.Reference + 1, // 29: hashicorp.consul.mesh.v1alpha1.ComputedRoutes.PortedConfigsEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes + 11, // 30: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.TargetsEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.BackendTargetDetails + 31, // [31:31] is the sub-list for method output_type + 31, // [31:31] is the sub-list for method input_type + 31, // [31:31] is the sub-list for extension type_name + 31, // [31:31] is the sub-list for extension extendee + 0, // [0:31] is the sub-list for field type_name } func init() { file_pbmesh_v1alpha1_computed_routes_proto_init() } diff --git a/proto-public/pbmesh/v1alpha1/computed_routes.proto b/proto-public/pbmesh/v1alpha1/computed_routes.proto index 4407a48c77c8..8b58c7b37f6d 100644 --- a/proto-public/pbmesh/v1alpha1/computed_routes.proto +++ b/proto-public/pbmesh/v1alpha1/computed_routes.proto @@ -6,13 +6,15 @@ syntax = "proto3"; package hashicorp.consul.mesh.v1alpha1; import "pbcatalog/v1alpha1/failover_policy.proto"; -import "pbcatalog/v1alpha1/service.proto"; +import "pbcatalog/v1alpha1/protocol.proto"; +import "pbcatalog/v1alpha1/service_endpoints.proto"; import "pbmesh/v1alpha1/common.proto"; import "pbmesh/v1alpha1/destination_policy.proto"; import "pbmesh/v1alpha1/grpc_route.proto"; import "pbmesh/v1alpha1/http_route.proto"; import "pbmesh/v1alpha1/http_route_retries.proto"; import "pbmesh/v1alpha1/http_route_timeouts.proto"; +import "pbresource/resource.proto"; // This is a Resource type. message ComputedRoutes { @@ -27,14 +29,19 @@ message ComputedPortRoutes { } bool using_default_config = 4; // TODO + ParentReference parent_ref = 5; + // Protocol is the ParentRef.Port's protocol. It is based on the value in the + // Service object, but may differ depending upon which xRoutes are actually + // in use. + hashicorp.consul.catalog.v1alpha1.Protocol protocol = 6; + // map key is an opaque string; like disco chain target name - map targets = 5; + map targets = 7; } message ComputedHTTPRoute { - ParentReference parent_ref = 1; - reserved 2; // hostnames - repeated ComputedHTTPRouteRule rules = 3; + reserved 1; // hostnames + repeated ComputedHTTPRouteRule rules = 2; } message ComputedHTTPRouteRule { @@ -59,9 +66,8 @@ message ComputedHTTPBackendRef { } message ComputedGRPCRoute { - ParentReference parent_ref = 1; - reserved 2; // hostnames - repeated ComputedGRPCRouteRule rules = 3; + reserved 1; // hostnames + repeated ComputedGRPCRouteRule rules = 2; } message ComputedGRPCRouteRule { @@ -86,8 +92,7 @@ message ComputedGRPCBackendRef { } message ComputedTCPRoute { - ParentReference parent_ref = 1; - repeated ComputedTCPRouteRule rules = 2; + repeated ComputedTCPRouteRule rules = 1; } message ComputedTCPRouteRule { @@ -112,7 +117,21 @@ message BackendTargetDetails { // identity info BackendReference backend_ref = 1; - hashicorp.consul.catalog.v1alpha1.Service service = 3; - hashicorp.consul.catalog.v1alpha1.FailoverPolicy failover_policy = 4; - DestinationPolicy destination_policy = 5; + string mesh_port = 2; + hashicorp.consul.catalog.v1alpha1.FailoverConfig failover_config = 3; + DestinationConfig destination_config = 4; + + reserved 5 to 20; // leaving a gap between computed and retroactively added fields. + + // ServiceEndpointsID is not populated naturally and the field exists only for + // downstream consumers. + hashicorp.consul.resource.ID service_endpoints_id = 21; + + // ServiceEndpoints is not populated naturally and the field exists only for + // downstream consumers. + hashicorp.consul.catalog.v1alpha1.ServiceEndpoints service_endpoints = 22; + + // IdentityRefs are not populated naturally and the field exists only for + // downstream consumers. + repeated hashicorp.consul.resource.Reference identity_refs = 23; } diff --git a/proto-public/pbmesh/v1alpha1/http_route_retries.pb.go b/proto-public/pbmesh/v1alpha1/http_route_retries.pb.go index 5a34d26a3260..93435881b230 100644 --- a/proto-public/pbmesh/v1alpha1/http_route_retries.pb.go +++ b/proto-public/pbmesh/v1alpha1/http_route_retries.pb.go @@ -12,6 +12,7 @@ package meshv1alpha1 import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" reflect "reflect" sync "sync" ) @@ -23,15 +24,14 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// ALTERNATIVE: not using policy attachment semantics type HTTPRouteRetries struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // NumRetries is the number of times to retry the request when a retryable + // Number is the number of times to retry the request when a retryable // result occurs. - Number int32 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"` + Number *wrapperspb.UInt32Value `protobuf:"bytes,1,opt,name=number,proto3" json:"number,omitempty"` // RetryOnConnectFailure allows for connection failure errors to trigger a // retry. OnConnectFailure bool `protobuf:"varint,2,opt,name=on_connect_failure,json=onConnectFailure,proto3" json:"on_connect_failure,omitempty"` @@ -75,11 +75,11 @@ func (*HTTPRouteRetries) Descriptor() ([]byte, []int) { return file_pbmesh_v1alpha1_http_route_retries_proto_rawDescGZIP(), []int{0} } -func (x *HTTPRouteRetries) GetNumber() int32 { +func (x *HTTPRouteRetries) GetNumber() *wrapperspb.UInt32Value { if x != nil { return x.Number } - return 0 + return nil } func (x *HTTPRouteRetries) GetOnConnectFailure() bool { @@ -110,36 +110,40 @@ var file_pbmesh_v1alpha1_http_route_retries_proto_rawDesc = []byte{ 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x22, 0xa5, 0x01, 0x0a, 0x10, 0x48, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, + 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc3, 0x01, 0x0a, 0x10, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, - 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x12, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x10, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x46, 0x61, - 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x6e, - 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6f, 0x6e, - 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x0d, 0x52, 0x0d, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, - 0x65, 0x73, 0x42, 0x9d, 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x15, 0x48, 0x74, 0x74, 0x70, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x45, 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, 0x6d, - 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, - 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, - 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0xca, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0xe2, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x34, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x6e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x12, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x10, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x46, 0x61, 0x69, 0x6c, + 0x75, 0x72, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x6e, 0x43, 0x6f, + 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6f, 0x6e, 0x5f, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x0d, 0x52, 0x0d, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x73, + 0x42, 0x9d, 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x15, 0x48, 0x74, 0x74, 0x70, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x45, 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, 0x6d, 0x65, 0x73, + 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1e, + 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, + 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, + 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, 0x48, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -156,14 +160,16 @@ func file_pbmesh_v1alpha1_http_route_retries_proto_rawDescGZIP() []byte { var file_pbmesh_v1alpha1_http_route_retries_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_pbmesh_v1alpha1_http_route_retries_proto_goTypes = []interface{}{ - (*HTTPRouteRetries)(nil), // 0: hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries + (*HTTPRouteRetries)(nil), // 0: hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries + (*wrapperspb.UInt32Value)(nil), // 1: google.protobuf.UInt32Value } var file_pbmesh_v1alpha1_http_route_retries_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name + 1, // 0: hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries.number:type_name -> google.protobuf.UInt32Value + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name } func init() { file_pbmesh_v1alpha1_http_route_retries_proto_init() } diff --git a/proto-public/pbmesh/v1alpha1/http_route_retries.proto b/proto-public/pbmesh/v1alpha1/http_route_retries.proto index 3ea112027abe..f0b8ccd3cf25 100644 --- a/proto-public/pbmesh/v1alpha1/http_route_retries.proto +++ b/proto-public/pbmesh/v1alpha1/http_route_retries.proto @@ -5,11 +5,12 @@ syntax = "proto3"; package hashicorp.consul.mesh.v1alpha1; -// ALTERNATIVE: not using policy attachment semantics +import "google/protobuf/wrappers.proto"; + message HTTPRouteRetries { - // NumRetries is the number of times to retry the request when a retryable + // Number is the number of times to retry the request when a retryable // result occurs. - int32 number = 1; + google.protobuf.UInt32Value number = 1; // RetryOnConnectFailure allows for connection failure errors to trigger a // retry. diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.binary.go b/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.binary.go index 54087655a2c8..b616e6f833f9 100644 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.binary.go +++ b/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.binary.go @@ -87,6 +87,16 @@ func (msg *StaticEndpointGroup) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *DestinationCluster) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *DestinationCluster) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + // MarshalBinary implements encoding.BinaryMarshaler func (msg *L4WeightedClusterGroup) MarshalBinary() ([]byte, error) { return proto.Marshal(msg) diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.go b/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.go index a641988f422a..b8f23158f5b5 100644 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.go +++ b/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.go @@ -635,6 +635,54 @@ func (x *StaticEndpointGroup) GetConfig() *StaticEndpointGroupConfig { return nil } +type DestinationCluster struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // name is the name of the cluster. This will be used to look up a cluster in the clusters map. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *DestinationCluster) Reset() { + *x = DestinationCluster{} + if protoimpl.UnsafeEnabled { + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DestinationCluster) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DestinationCluster) ProtoMessage() {} + +func (x *DestinationCluster) ProtoReflect() protoreflect.Message { + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DestinationCluster.ProtoReflect.Descriptor instead. +func (*DestinationCluster) Descriptor() ([]byte, []int) { + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{8} +} + +func (x *DestinationCluster) GetName() string { + if x != nil { + return x.Name + } + return "" +} + type L4WeightedClusterGroup struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -647,7 +695,7 @@ type L4WeightedClusterGroup struct { func (x *L4WeightedClusterGroup) Reset() { *x = L4WeightedClusterGroup{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[8] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -660,7 +708,7 @@ func (x *L4WeightedClusterGroup) String() string { func (*L4WeightedClusterGroup) ProtoMessage() {} func (x *L4WeightedClusterGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[8] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -673,7 +721,7 @@ func (x *L4WeightedClusterGroup) ProtoReflect() protoreflect.Message { // Deprecated: Use L4WeightedClusterGroup.ProtoReflect.Descriptor instead. func (*L4WeightedClusterGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{8} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{9} } func (x *L4WeightedClusterGroup) GetClusters() []*L4WeightedDestinationCluster { @@ -695,7 +743,7 @@ type L7WeightedClusterGroup struct { func (x *L7WeightedClusterGroup) Reset() { *x = L7WeightedClusterGroup{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[9] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -708,7 +756,7 @@ func (x *L7WeightedClusterGroup) String() string { func (*L7WeightedClusterGroup) ProtoMessage() {} func (x *L7WeightedClusterGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[9] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -721,7 +769,7 @@ func (x *L7WeightedClusterGroup) ProtoReflect() protoreflect.Message { // Deprecated: Use L7WeightedClusterGroup.ProtoReflect.Descriptor instead. func (*L7WeightedClusterGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{9} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{10} } func (x *L7WeightedClusterGroup) GetClusters() []*L7WeightedDestinationCluster { @@ -744,7 +792,7 @@ type L4WeightedDestinationCluster struct { func (x *L4WeightedDestinationCluster) Reset() { *x = L4WeightedDestinationCluster{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[10] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -757,7 +805,7 @@ func (x *L4WeightedDestinationCluster) String() string { func (*L4WeightedDestinationCluster) ProtoMessage() {} func (x *L4WeightedDestinationCluster) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[10] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -770,7 +818,7 @@ func (x *L4WeightedDestinationCluster) ProtoReflect() protoreflect.Message { // Deprecated: Use L4WeightedDestinationCluster.ProtoReflect.Descriptor instead. func (*L4WeightedDestinationCluster) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{10} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{11} } func (x *L4WeightedDestinationCluster) GetName() string { @@ -801,7 +849,7 @@ type L7WeightedDestinationCluster struct { func (x *L7WeightedDestinationCluster) Reset() { *x = L7WeightedDestinationCluster{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[11] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -814,7 +862,7 @@ func (x *L7WeightedDestinationCluster) String() string { func (*L7WeightedDestinationCluster) ProtoMessage() {} func (x *L7WeightedDestinationCluster) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[11] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -827,7 +875,7 @@ func (x *L7WeightedDestinationCluster) ProtoReflect() protoreflect.Message { // Deprecated: Use L7WeightedDestinationCluster.ProtoReflect.Descriptor instead. func (*L7WeightedDestinationCluster) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{11} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{12} } func (x *L7WeightedDestinationCluster) GetName() string { @@ -875,7 +923,7 @@ type DynamicEndpointGroupConfig struct { func (x *DynamicEndpointGroupConfig) Reset() { *x = DynamicEndpointGroupConfig{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[12] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -888,7 +936,7 @@ func (x *DynamicEndpointGroupConfig) String() string { func (*DynamicEndpointGroupConfig) ProtoMessage() {} func (x *DynamicEndpointGroupConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[12] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -901,7 +949,7 @@ func (x *DynamicEndpointGroupConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use DynamicEndpointGroupConfig.ProtoReflect.Descriptor instead. func (*DynamicEndpointGroupConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{12} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{13} } func (x *DynamicEndpointGroupConfig) GetConnectTimeout() *durationpb.Duration { @@ -1033,7 +1081,7 @@ type LBPolicyLeastRequest struct { func (x *LBPolicyLeastRequest) Reset() { *x = LBPolicyLeastRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[13] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1046,7 +1094,7 @@ func (x *LBPolicyLeastRequest) String() string { func (*LBPolicyLeastRequest) ProtoMessage() {} func (x *LBPolicyLeastRequest) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[13] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1059,7 +1107,7 @@ func (x *LBPolicyLeastRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use LBPolicyLeastRequest.ProtoReflect.Descriptor instead. func (*LBPolicyLeastRequest) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{13} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{14} } func (x *LBPolicyLeastRequest) GetChoiceCount() *wrapperspb.UInt32Value { @@ -1078,7 +1126,7 @@ type LBPolicyRoundRobin struct { func (x *LBPolicyRoundRobin) Reset() { *x = LBPolicyRoundRobin{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[14] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1091,7 +1139,7 @@ func (x *LBPolicyRoundRobin) String() string { func (*LBPolicyRoundRobin) ProtoMessage() {} func (x *LBPolicyRoundRobin) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[14] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1104,7 +1152,7 @@ func (x *LBPolicyRoundRobin) ProtoReflect() protoreflect.Message { // Deprecated: Use LBPolicyRoundRobin.ProtoReflect.Descriptor instead. func (*LBPolicyRoundRobin) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{14} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{15} } type LBPolicyRandom struct { @@ -1116,7 +1164,7 @@ type LBPolicyRandom struct { func (x *LBPolicyRandom) Reset() { *x = LBPolicyRandom{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[15] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1129,7 +1177,7 @@ func (x *LBPolicyRandom) String() string { func (*LBPolicyRandom) ProtoMessage() {} func (x *LBPolicyRandom) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[15] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1142,7 +1190,7 @@ func (x *LBPolicyRandom) ProtoReflect() protoreflect.Message { // Deprecated: Use LBPolicyRandom.ProtoReflect.Descriptor instead. func (*LBPolicyRandom) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{15} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{16} } type LBPolicyRingHash struct { @@ -1157,7 +1205,7 @@ type LBPolicyRingHash struct { func (x *LBPolicyRingHash) Reset() { *x = LBPolicyRingHash{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[16] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1170,7 +1218,7 @@ func (x *LBPolicyRingHash) String() string { func (*LBPolicyRingHash) ProtoMessage() {} func (x *LBPolicyRingHash) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[16] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1183,7 +1231,7 @@ func (x *LBPolicyRingHash) ProtoReflect() protoreflect.Message { // Deprecated: Use LBPolicyRingHash.ProtoReflect.Descriptor instead. func (*LBPolicyRingHash) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{16} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{17} } func (x *LBPolicyRingHash) GetMinimumRingSize() *wrapperspb.UInt64Value { @@ -1209,7 +1257,7 @@ type LBPolicyMaglev struct { func (x *LBPolicyMaglev) Reset() { *x = LBPolicyMaglev{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[17] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1222,7 +1270,7 @@ func (x *LBPolicyMaglev) String() string { func (*LBPolicyMaglev) ProtoMessage() {} func (x *LBPolicyMaglev) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[17] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1235,7 +1283,7 @@ func (x *LBPolicyMaglev) ProtoReflect() protoreflect.Message { // Deprecated: Use LBPolicyMaglev.ProtoReflect.Descriptor instead. func (*LBPolicyMaglev) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{17} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{18} } type CircuitBreakers struct { @@ -1249,7 +1297,7 @@ type CircuitBreakers struct { func (x *CircuitBreakers) Reset() { *x = CircuitBreakers{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[18] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1262,7 +1310,7 @@ func (x *CircuitBreakers) String() string { func (*CircuitBreakers) ProtoMessage() {} func (x *CircuitBreakers) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[18] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1275,7 +1323,7 @@ func (x *CircuitBreakers) ProtoReflect() protoreflect.Message { // Deprecated: Use CircuitBreakers.ProtoReflect.Descriptor instead. func (*CircuitBreakers) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{18} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{19} } func (x *CircuitBreakers) GetUpstreamLimits() *UpstreamLimits { @@ -1298,7 +1346,7 @@ type UpstreamLimits struct { func (x *UpstreamLimits) Reset() { *x = UpstreamLimits{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[19] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1311,7 +1359,7 @@ func (x *UpstreamLimits) String() string { func (*UpstreamLimits) ProtoMessage() {} func (x *UpstreamLimits) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[19] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1324,7 +1372,7 @@ func (x *UpstreamLimits) ProtoReflect() protoreflect.Message { // Deprecated: Use UpstreamLimits.ProtoReflect.Descriptor instead. func (*UpstreamLimits) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{19} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{20} } func (x *UpstreamLimits) GetMaxConnections() *wrapperspb.UInt32Value { @@ -1363,7 +1411,7 @@ type OutlierDetection struct { func (x *OutlierDetection) Reset() { *x = OutlierDetection{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[20] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1376,7 +1424,7 @@ func (x *OutlierDetection) String() string { func (*OutlierDetection) ProtoMessage() {} func (x *OutlierDetection) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[20] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1389,7 +1437,7 @@ func (x *OutlierDetection) ProtoReflect() protoreflect.Message { // Deprecated: Use OutlierDetection.ProtoReflect.Descriptor instead. func (*OutlierDetection) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{20} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{21} } func (x *OutlierDetection) GetInterval() *durationpb.Duration { @@ -1440,7 +1488,7 @@ type UpstreamConnectionOptions struct { func (x *UpstreamConnectionOptions) Reset() { *x = UpstreamConnectionOptions{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[21] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1453,7 +1501,7 @@ func (x *UpstreamConnectionOptions) String() string { func (*UpstreamConnectionOptions) ProtoMessage() {} func (x *UpstreamConnectionOptions) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[21] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1466,7 +1514,7 @@ func (x *UpstreamConnectionOptions) ProtoReflect() protoreflect.Message { // Deprecated: Use UpstreamConnectionOptions.ProtoReflect.Descriptor instead. func (*UpstreamConnectionOptions) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{21} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{22} } func (x *UpstreamConnectionOptions) GetTcpKeepaliveTime() *wrapperspb.UInt32Value { @@ -1501,7 +1549,7 @@ type PassthroughEndpointGroupConfig struct { func (x *PassthroughEndpointGroupConfig) Reset() { *x = PassthroughEndpointGroupConfig{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[22] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1514,7 +1562,7 @@ func (x *PassthroughEndpointGroupConfig) String() string { func (*PassthroughEndpointGroupConfig) ProtoMessage() {} func (x *PassthroughEndpointGroupConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[22] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1527,7 +1575,7 @@ func (x *PassthroughEndpointGroupConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use PassthroughEndpointGroupConfig.ProtoReflect.Descriptor instead. func (*PassthroughEndpointGroupConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{22} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{23} } func (x *PassthroughEndpointGroupConfig) GetConnectTimeout() *durationpb.Duration { @@ -1554,7 +1602,7 @@ type DNSEndpointGroupConfig struct { func (x *DNSEndpointGroupConfig) Reset() { *x = DNSEndpointGroupConfig{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[23] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1567,7 +1615,7 @@ func (x *DNSEndpointGroupConfig) String() string { func (*DNSEndpointGroupConfig) ProtoMessage() {} func (x *DNSEndpointGroupConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[23] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1580,7 +1628,7 @@ func (x *DNSEndpointGroupConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use DNSEndpointGroupConfig.ProtoReflect.Descriptor instead. func (*DNSEndpointGroupConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{23} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{24} } func (x *DNSEndpointGroupConfig) GetConnectTimeout() *durationpb.Duration { @@ -1644,7 +1692,7 @@ type StaticEndpointGroupConfig struct { func (x *StaticEndpointGroupConfig) Reset() { *x = StaticEndpointGroupConfig{} if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[24] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1657,7 +1705,7 @@ func (x *StaticEndpointGroupConfig) String() string { func (*StaticEndpointGroupConfig) ProtoMessage() {} func (x *StaticEndpointGroupConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[24] + mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1670,7 +1718,7 @@ func (x *StaticEndpointGroupConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use StaticEndpointGroupConfig.ProtoReflect.Descriptor instead. func (*StaticEndpointGroupConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{24} + return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{25} } func (x *StaticEndpointGroupConfig) GetConnectTimeout() *durationpb.Duration { @@ -1824,43 +1872,201 @@ var file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDesc = []byte{ 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x7f, 0x0a, 0x16, 0x4c, 0x34, 0x57, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, - 0x65, 0x0a, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x49, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x28, 0x0a, 0x12, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, + 0x7f, 0x0a, 0x16, 0x4c, 0x34, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x65, 0x0a, 0x08, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, + 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, + 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x34, 0x57, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x65, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, + 0x22, 0x7f, 0x0a, 0x16, 0x4c, 0x37, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x43, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x65, 0x0a, 0x08, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, + 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x37, 0x57, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x65, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x73, 0x22, 0x68, 0x0a, 0x1c, 0x4c, 0x34, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x44, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0xd0, 0x01, 0x0a, 0x1c, + 0x4c, 0x37, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x34, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, + 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x66, 0x0a, 0x10, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x88, + 0x08, 0x0a, 0x1a, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, + 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, + 0x74, 0x12, 0x36, 0x0a, 0x17, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x6e, + 0x69, 0x63, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x6e, 0x69, 0x63, + 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x68, 0x0a, 0x0d, 0x6c, 0x65, 0x61, + 0x73, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, + 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x62, 0x0a, 0x0b, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x72, 0x6f, 0x62, + 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, + 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, + 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x62, 0x69, 0x6e, 0x48, 0x00, 0x52, 0x0a, 0x72, 0x6f, 0x75, + 0x6e, 0x64, 0x52, 0x6f, 0x62, 0x69, 0x6e, 0x12, 0x55, 0x0a, 0x06, 0x72, 0x61, 0x6e, 0x64, 0x6f, + 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x61, + 0x6e, 0x64, 0x6f, 0x6d, 0x48, 0x00, 0x52, 0x06, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x12, 0x5c, + 0x0a, 0x09, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, - 0x4c, 0x34, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x22, 0x7f, 0x0a, 0x16, 0x4c, 0x37, 0x57, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x12, 0x65, 0x0a, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x4c, 0x37, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, - 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x22, 0x68, 0x0a, 0x1c, 0x4c, 0x34, 0x57, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x65, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x77, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, - 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x22, 0xd0, 0x01, 0x0a, 0x1c, 0x4c, 0x37, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, - 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, + 0x48, 0x00, 0x52, 0x08, 0x72, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x12, 0x55, 0x0a, 0x06, + 0x6d, 0x61, 0x67, 0x6c, 0x65, 0x76, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, + 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x4d, 0x61, 0x67, 0x6c, 0x65, 0x76, 0x48, 0x00, 0x52, 0x06, 0x6d, 0x61, 0x67, + 0x6c, 0x65, 0x76, 0x12, 0x67, 0x0a, 0x10, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x5f, 0x62, + 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, + 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x69, 0x72, 0x63, + 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x0f, 0x63, 0x69, 0x72, + 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x6a, 0x0a, 0x11, + 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x44, 0x65, 0x74, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x44, + 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x86, 0x01, 0x0a, 0x1b, 0x75, 0x70, 0x73, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x46, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x55, 0x70, 0x73, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x19, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x29, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x5f, 0x61, 0x6c, 0x74, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x75, 0x73, + 0x65, 0x41, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x42, 0x0b, 0x0a, 0x09, + 0x6c, 0x62, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x57, 0x0a, 0x14, 0x4c, 0x42, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x3f, 0x0a, 0x0c, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0b, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x22, 0x14, 0x0a, 0x12, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x6f, + 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x62, 0x69, 0x6e, 0x22, 0x10, 0x0a, 0x0e, 0x4c, 0x42, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x22, 0xa6, 0x01, 0x0a, 0x10, 0x4c, + 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x12, + 0x48, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x72, 0x69, 0x6e, 0x67, 0x5f, + 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, + 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, + 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x48, 0x0a, 0x11, 0x6d, 0x61, 0x78, + 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, + 0x69, 0x7a, 0x65, 0x22, 0x10, 0x0a, 0x0e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4d, + 0x61, 0x67, 0x6c, 0x65, 0x76, 0x22, 0x77, 0x0a, 0x0f, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, + 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x64, 0x0a, 0x0f, 0x75, 0x70, 0x73, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, + 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x0e, + 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x22, 0xfd, + 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, + 0x73, 0x12, 0x45, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, + 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4e, 0x0a, 0x14, 0x6d, 0x61, 0x78, 0x5f, + 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x66, 0x0a, 0x10, - 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x88, 0x08, 0x0a, 0x1a, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x6d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x54, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, + 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, + 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x15, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, + 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, 0x83, + 0x03, 0x0a, 0x10, 0x4f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x45, 0x0a, 0x0f, 0x63, 0x6f, + 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x35, 0x78, 0x78, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, 0x78, + 0x78, 0x12, 0x58, 0x0a, 0x19, 0x65, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x63, + 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x35, 0x78, 0x78, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x17, 0x65, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, + 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, 0x78, 0x78, 0x12, 0x4e, 0x0a, 0x14, 0x6d, + 0x61, 0x78, 0x5f, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x65, 0x72, 0x63, + 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, + 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x6d, 0x61, 0x78, 0x45, 0x6a, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x12, 0x62, + 0x61, 0x73, 0x65, 0x5f, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x10, 0x62, 0x61, 0x73, 0x65, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x69, 0x6d, 0x65, 0x22, 0x8b, 0x02, 0x0a, 0x19, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x4a, 0x0a, 0x12, 0x74, 0x63, 0x70, 0x5f, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, + 0x69, 0x76, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x10, 0x74, 0x63, + 0x70, 0x4b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x52, + 0x0a, 0x16, 0x74, 0x63, 0x70, 0x5f, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x5f, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x14, 0x74, 0x63, + 0x70, 0x4b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, + 0x61, 0x6c, 0x12, 0x4e, 0x0a, 0x14, 0x74, 0x63, 0x70, 0x5f, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, + 0x69, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, + 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x50, 0x72, 0x6f, 0x62, + 0x65, 0x73, 0x22, 0x64, 0x0a, 0x1e, 0x50, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, + 0x68, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x80, 0x05, 0x0a, 0x16, 0x44, 0x4e, 0x53, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, @@ -1870,232 +2076,77 @@ var file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDesc = []byte{ 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x6e, 0x69, 0x63, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, - 0x68, 0x0a, 0x0d, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x65, 0x61, - 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x6c, 0x65, 0x61, - 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x62, 0x0a, 0x0b, 0x72, 0x6f, 0x75, - 0x6e, 0x64, 0x5f, 0x72, 0x6f, 0x62, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x42, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x62, 0x69, 0x6e, 0x48, - 0x00, 0x52, 0x0a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x62, 0x69, 0x6e, 0x12, 0x55, 0x0a, - 0x06, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x42, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x48, 0x00, 0x52, 0x06, 0x72, 0x61, - 0x6e, 0x64, 0x6f, 0x6d, 0x12, 0x5c, 0x0a, 0x09, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x73, - 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x61, 0x0a, 0x0e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x69, - 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x48, 0x00, 0x52, 0x08, 0x72, 0x69, 0x6e, 0x67, 0x48, 0x61, - 0x73, 0x68, 0x12, 0x55, 0x0a, 0x06, 0x6d, 0x61, 0x67, 0x6c, 0x65, 0x76, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4d, 0x61, 0x67, 0x6c, 0x65, 0x76, 0x48, - 0x00, 0x52, 0x06, 0x6d, 0x61, 0x67, 0x6c, 0x65, 0x76, 0x12, 0x67, 0x0a, 0x10, 0x63, 0x69, 0x72, - 0x63, 0x75, 0x69, 0x74, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, - 0x73, 0x52, 0x0f, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, - 0x72, 0x73, 0x12, 0x6a, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x64, 0x65, - 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x67, 0x0a, 0x10, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x5f, 0x62, 0x72, + 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, + 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x69, 0x72, 0x63, 0x75, + 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x0f, 0x63, 0x69, 0x72, 0x63, + 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x6a, 0x0a, 0x11, 0x6f, + 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x44, 0x65, 0x74, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x44, 0x65, + 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x86, 0x01, 0x0a, 0x1b, 0x75, 0x70, 0x73, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x6c, - 0x69, 0x65, 0x72, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x6f, 0x75, - 0x74, 0x6c, 0x69, 0x65, 0x72, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x86, - 0x01, 0x0a, 0x1b, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x19, 0x75, 0x70, - 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x5f, 0x61, - 0x6c, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x41, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x4e, 0x61, - 0x6d, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x6c, 0x62, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, - 0x57, 0x0a, 0x14, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x65, 0x61, 0x73, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x0c, 0x63, 0x68, 0x6f, 0x69, 0x63, - 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0b, 0x63, 0x68, 0x6f, - 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x14, 0x0a, 0x12, 0x4c, 0x42, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x62, 0x69, 0x6e, 0x22, 0x10, - 0x0a, 0x0e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, - 0x22, 0xa6, 0x01, 0x0a, 0x10, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x69, 0x6e, - 0x67, 0x48, 0x61, 0x73, 0x68, 0x12, 0x48, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, - 0x5f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, - 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x12, - 0x48, 0x0a, 0x11, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x72, 0x69, 0x6e, 0x67, 0x5f, - 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, - 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, - 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x10, 0x0a, 0x0e, 0x4c, 0x42, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4d, 0x61, 0x67, 0x6c, 0x65, 0x76, 0x22, 0x77, 0x0a, 0x0f, 0x43, - 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x64, - 0x0a, 0x0f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, - 0x6d, 0x69, 0x74, 0x73, 0x52, 0x0e, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, - 0x6d, 0x69, 0x74, 0x73, 0x22, 0xfd, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, - 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4e, - 0x0a, 0x14, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x6d, 0x61, 0x78, 0x50, - 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x54, - 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, - 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x15, 0x6d, - 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x73, 0x22, 0x83, 0x03, 0x0a, 0x10, 0x4f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, - 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x08, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, - 0x12, 0x45, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f, - 0x35, 0x78, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, - 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x76, 0x65, 0x35, 0x78, 0x78, 0x12, 0x58, 0x0a, 0x19, 0x65, 0x6e, 0x66, 0x6f, 0x72, - 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, - 0x5f, 0x35, 0x78, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, - 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x17, 0x65, 0x6e, 0x66, 0x6f, 0x72, 0x63, - 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, 0x78, - 0x78, 0x12, 0x4e, 0x0a, 0x14, 0x6d, 0x61, 0x78, 0x5f, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x6d, - 0x61, 0x78, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, - 0x74, 0x12, 0x47, 0x0a, 0x12, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x62, 0x61, 0x73, 0x65, 0x45, 0x6a, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x8b, 0x02, 0x0a, 0x19, 0x55, - 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4a, 0x0a, 0x12, 0x74, 0x63, 0x70, 0x5f, - 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x10, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, - 0x54, 0x69, 0x6d, 0x65, 0x12, 0x52, 0x0a, 0x16, 0x74, 0x63, 0x70, 0x5f, 0x6b, 0x65, 0x65, 0x70, - 0x61, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x14, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x4e, 0x0a, 0x14, 0x74, 0x63, 0x70, 0x5f, - 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, - 0x76, 0x65, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x73, 0x22, 0x64, 0x0a, 0x1e, 0x50, 0x61, 0x73, 0x73, - 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, - 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x80, - 0x05, 0x0a, 0x16, 0x44, 0x4e, 0x53, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, + 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x55, 0x70, 0x73, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x19, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x29, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x5f, 0x61, 0x6c, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x75, 0x73, 0x65, + 0x41, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xc8, 0x01, 0x0a, 0x19, + 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x36, 0x0a, - 0x17, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x6e, 0x69, 0x63, 0x5f, 0x74, - 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, - 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x54, 0x68, 0x72, 0x65, - 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x61, 0x0a, 0x0e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, - 0x72, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x67, 0x0a, 0x10, 0x63, 0x69, 0x72, 0x63, - 0x75, 0x69, 0x74, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, - 0x52, 0x0f, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, - 0x73, 0x12, 0x6a, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x6c, 0x69, - 0x65, 0x72, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x6f, 0x75, 0x74, - 0x6c, 0x69, 0x65, 0x72, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x86, 0x01, - 0x0a, 0x1b, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x19, 0x75, 0x70, 0x73, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x5f, 0x61, 0x6c, - 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x41, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x4e, 0x61, 0x6d, - 0x65, 0x22, 0xc8, 0x01, 0x0a, 0x19, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x12, 0x67, 0x0a, 0x10, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x5f, 0x62, - 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x69, 0x72, 0x63, - 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x0f, 0x63, 0x69, 0x72, - 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x2a, 0x46, 0x0a, 0x0d, - 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, - 0x16, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x4c, 0x4f, 0x47, 0x49, 0x43, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x49, 0x53, - 0x43, 0x4f, 0x56, 0x45, 0x52, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, - 0x43, 0x54, 0x10, 0x01, 0x42, 0xd8, 0x02, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, - 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, - 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0xe2, 0x02, 0x37, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2f, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x67, 0x0a, + 0x10, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, + 0x61, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x0f, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, + 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x2a, 0x46, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x44, 0x49, 0x53, 0x43, 0x4f, + 0x56, 0x45, 0x52, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x4f, 0x47, 0x49, 0x43, 0x41, + 0x4c, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x59, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x43, 0x54, 0x10, 0x01, 0x42, 0xd8, + 0x02, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x42, 0x0c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x45, 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, 0x6d, + 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, + 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, + 0x50, 0xaa, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, + 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x37, + 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, + 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2f, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, + 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, + 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -2111,7 +2162,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP() []byte { } var file_pbmesh_v1alpha1_pbproxystate_cluster_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes = make([]protoimpl.MessageInfo, 25) +var file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes = make([]protoimpl.MessageInfo, 26) var file_pbmesh_v1alpha1_pbproxystate_cluster_proto_goTypes = []interface{}{ (DiscoveryType)(0), // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.DiscoveryType (*Cluster)(nil), // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.Cluster @@ -2122,83 +2173,84 @@ var file_pbmesh_v1alpha1_pbproxystate_cluster_proto_goTypes = []interface{}{ (*PassthroughEndpointGroup)(nil), // 6: hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroup (*DNSEndpointGroup)(nil), // 7: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroup (*StaticEndpointGroup)(nil), // 8: hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroup - (*L4WeightedClusterGroup)(nil), // 9: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedClusterGroup - (*L7WeightedClusterGroup)(nil), // 10: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedClusterGroup - (*L4WeightedDestinationCluster)(nil), // 11: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedDestinationCluster - (*L7WeightedDestinationCluster)(nil), // 12: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedDestinationCluster - (*DynamicEndpointGroupConfig)(nil), // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig - (*LBPolicyLeastRequest)(nil), // 14: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyLeastRequest - (*LBPolicyRoundRobin)(nil), // 15: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRoundRobin - (*LBPolicyRandom)(nil), // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRandom - (*LBPolicyRingHash)(nil), // 17: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRingHash - (*LBPolicyMaglev)(nil), // 18: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyMaglev - (*CircuitBreakers)(nil), // 19: hashicorp.consul.mesh.v1alpha1.pbproxystate.CircuitBreakers - (*UpstreamLimits)(nil), // 20: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamLimits - (*OutlierDetection)(nil), // 21: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection - (*UpstreamConnectionOptions)(nil), // 22: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions - (*PassthroughEndpointGroupConfig)(nil), // 23: hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroupConfig - (*DNSEndpointGroupConfig)(nil), // 24: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig - (*StaticEndpointGroupConfig)(nil), // 25: hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroupConfig - (*durationpb.Duration)(nil), // 26: google.protobuf.Duration - (*TransportSocket)(nil), // 27: hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket - (*wrapperspb.UInt32Value)(nil), // 28: google.protobuf.UInt32Value - (*HeaderMutation)(nil), // 29: hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation - (*wrapperspb.UInt64Value)(nil), // 30: google.protobuf.UInt64Value + (*DestinationCluster)(nil), // 9: hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationCluster + (*L4WeightedClusterGroup)(nil), // 10: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedClusterGroup + (*L7WeightedClusterGroup)(nil), // 11: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedClusterGroup + (*L4WeightedDestinationCluster)(nil), // 12: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedDestinationCluster + (*L7WeightedDestinationCluster)(nil), // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedDestinationCluster + (*DynamicEndpointGroupConfig)(nil), // 14: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig + (*LBPolicyLeastRequest)(nil), // 15: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyLeastRequest + (*LBPolicyRoundRobin)(nil), // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRoundRobin + (*LBPolicyRandom)(nil), // 17: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRandom + (*LBPolicyRingHash)(nil), // 18: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRingHash + (*LBPolicyMaglev)(nil), // 19: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyMaglev + (*CircuitBreakers)(nil), // 20: hashicorp.consul.mesh.v1alpha1.pbproxystate.CircuitBreakers + (*UpstreamLimits)(nil), // 21: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamLimits + (*OutlierDetection)(nil), // 22: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection + (*UpstreamConnectionOptions)(nil), // 23: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions + (*PassthroughEndpointGroupConfig)(nil), // 24: hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroupConfig + (*DNSEndpointGroupConfig)(nil), // 25: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig + (*StaticEndpointGroupConfig)(nil), // 26: hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroupConfig + (*durationpb.Duration)(nil), // 27: google.protobuf.Duration + (*TransportSocket)(nil), // 28: hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket + (*wrapperspb.UInt32Value)(nil), // 29: google.protobuf.UInt32Value + (*HeaderMutation)(nil), // 30: hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation + (*wrapperspb.UInt64Value)(nil), // 31: google.protobuf.UInt64Value } var file_pbmesh_v1alpha1_pbproxystate_cluster_proto_depIdxs = []int32{ 2, // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.Cluster.failover_group:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.FailoverGroup 4, // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.Cluster.endpoint_group:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointGroup 4, // 2: hashicorp.consul.mesh.v1alpha1.pbproxystate.FailoverGroup.endpoint_groups:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointGroup 3, // 3: hashicorp.consul.mesh.v1alpha1.pbproxystate.FailoverGroup.config:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.FailoverGroupConfig - 26, // 4: hashicorp.consul.mesh.v1alpha1.pbproxystate.FailoverGroupConfig.connect_timeout:type_name -> google.protobuf.Duration + 27, // 4: hashicorp.consul.mesh.v1alpha1.pbproxystate.FailoverGroupConfig.connect_timeout:type_name -> google.protobuf.Duration 5, // 5: hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointGroup.dynamic:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroup 8, // 6: hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointGroup.static:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroup 7, // 7: hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointGroup.dns:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroup 6, // 8: hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointGroup.passthrough:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroup - 13, // 9: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroup.config:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig - 27, // 10: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroup.outbound_tls:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket - 23, // 11: hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroup.config:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroupConfig - 27, // 12: hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroup.outbound_tls:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket - 24, // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroup.config:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig - 27, // 14: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroup.outbound_tls:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket - 25, // 15: hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroup.config:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroupConfig - 11, // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedClusterGroup.clusters:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedDestinationCluster - 12, // 17: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedClusterGroup.clusters:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedDestinationCluster - 28, // 18: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedDestinationCluster.weight:type_name -> google.protobuf.UInt32Value - 28, // 19: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedDestinationCluster.weight:type_name -> google.protobuf.UInt32Value - 29, // 20: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedDestinationCluster.header_mutations:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation - 26, // 21: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration - 14, // 22: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.least_request:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyLeastRequest - 15, // 23: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.round_robin:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRoundRobin - 16, // 24: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.random:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRandom - 17, // 25: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.ring_hash:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRingHash - 18, // 26: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.maglev:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyMaglev - 19, // 27: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.circuit_breakers:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.CircuitBreakers - 21, // 28: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.outlier_detection:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection - 22, // 29: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.upstream_connection_options:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions - 28, // 30: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyLeastRequest.choice_count:type_name -> google.protobuf.UInt32Value - 30, // 31: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRingHash.minimum_ring_size:type_name -> google.protobuf.UInt64Value - 30, // 32: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRingHash.maximum_ring_size:type_name -> google.protobuf.UInt64Value - 20, // 33: hashicorp.consul.mesh.v1alpha1.pbproxystate.CircuitBreakers.upstream_limits:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamLimits - 28, // 34: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamLimits.max_connections:type_name -> google.protobuf.UInt32Value - 28, // 35: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamLimits.max_pending_requests:type_name -> google.protobuf.UInt32Value - 28, // 36: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamLimits.max_concurrent_requests:type_name -> google.protobuf.UInt32Value - 26, // 37: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection.interval:type_name -> google.protobuf.Duration - 28, // 38: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection.consecutive_5xx:type_name -> google.protobuf.UInt32Value - 28, // 39: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection.enforcing_consecutive_5xx:type_name -> google.protobuf.UInt32Value - 28, // 40: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection.max_ejection_percent:type_name -> google.protobuf.UInt32Value - 26, // 41: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection.base_ejection_time:type_name -> google.protobuf.Duration - 28, // 42: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions.tcp_keepalive_time:type_name -> google.protobuf.UInt32Value - 28, // 43: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions.tcp_keepalive_interval:type_name -> google.protobuf.UInt32Value - 28, // 44: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions.tcp_keepalive_probes:type_name -> google.protobuf.UInt32Value - 26, // 45: hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration - 26, // 46: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration + 14, // 9: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroup.config:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig + 28, // 10: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroup.outbound_tls:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket + 24, // 11: hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroup.config:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroupConfig + 28, // 12: hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroup.outbound_tls:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket + 25, // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroup.config:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig + 28, // 14: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroup.outbound_tls:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket + 26, // 15: hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroup.config:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroupConfig + 12, // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedClusterGroup.clusters:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedDestinationCluster + 13, // 17: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedClusterGroup.clusters:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedDestinationCluster + 29, // 18: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedDestinationCluster.weight:type_name -> google.protobuf.UInt32Value + 29, // 19: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedDestinationCluster.weight:type_name -> google.protobuf.UInt32Value + 30, // 20: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedDestinationCluster.header_mutations:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation + 27, // 21: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration + 15, // 22: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.least_request:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyLeastRequest + 16, // 23: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.round_robin:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRoundRobin + 17, // 24: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.random:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRandom + 18, // 25: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.ring_hash:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRingHash + 19, // 26: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.maglev:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyMaglev + 20, // 27: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.circuit_breakers:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.CircuitBreakers + 22, // 28: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.outlier_detection:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection + 23, // 29: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.upstream_connection_options:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions + 29, // 30: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyLeastRequest.choice_count:type_name -> google.protobuf.UInt32Value + 31, // 31: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRingHash.minimum_ring_size:type_name -> google.protobuf.UInt64Value + 31, // 32: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRingHash.maximum_ring_size:type_name -> google.protobuf.UInt64Value + 21, // 33: hashicorp.consul.mesh.v1alpha1.pbproxystate.CircuitBreakers.upstream_limits:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamLimits + 29, // 34: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamLimits.max_connections:type_name -> google.protobuf.UInt32Value + 29, // 35: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamLimits.max_pending_requests:type_name -> google.protobuf.UInt32Value + 29, // 36: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamLimits.max_concurrent_requests:type_name -> google.protobuf.UInt32Value + 27, // 37: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection.interval:type_name -> google.protobuf.Duration + 29, // 38: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection.consecutive_5xx:type_name -> google.protobuf.UInt32Value + 29, // 39: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection.enforcing_consecutive_5xx:type_name -> google.protobuf.UInt32Value + 29, // 40: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection.max_ejection_percent:type_name -> google.protobuf.UInt32Value + 27, // 41: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection.base_ejection_time:type_name -> google.protobuf.Duration + 29, // 42: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions.tcp_keepalive_time:type_name -> google.protobuf.UInt32Value + 29, // 43: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions.tcp_keepalive_interval:type_name -> google.protobuf.UInt32Value + 29, // 44: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions.tcp_keepalive_probes:type_name -> google.protobuf.UInt32Value + 27, // 45: hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration + 27, // 46: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration 0, // 47: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig.discovery_type:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DiscoveryType - 19, // 48: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig.circuit_breakers:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.CircuitBreakers - 21, // 49: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig.outlier_detection:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection - 22, // 50: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig.upstream_connection_options:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions - 26, // 51: hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration - 19, // 52: hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroupConfig.circuit_breakers:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.CircuitBreakers + 20, // 48: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig.circuit_breakers:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.CircuitBreakers + 22, // 49: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig.outlier_detection:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection + 23, // 50: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig.upstream_connection_options:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions + 27, // 51: hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration + 20, // 52: hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroupConfig.circuit_breakers:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.CircuitBreakers 53, // [53:53] is the sub-list for method output_type 53, // [53:53] is the sub-list for method input_type 53, // [53:53] is the sub-list for extension type_name @@ -2311,7 +2363,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L4WeightedClusterGroup); i { + switch v := v.(*DestinationCluster); i { case 0: return &v.state case 1: @@ -2323,7 +2375,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L7WeightedClusterGroup); i { + switch v := v.(*L4WeightedClusterGroup); i { case 0: return &v.state case 1: @@ -2335,7 +2387,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L4WeightedDestinationCluster); i { + switch v := v.(*L7WeightedClusterGroup); i { case 0: return &v.state case 1: @@ -2347,7 +2399,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L7WeightedDestinationCluster); i { + switch v := v.(*L4WeightedDestinationCluster); i { case 0: return &v.state case 1: @@ -2359,7 +2411,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DynamicEndpointGroupConfig); i { + switch v := v.(*L7WeightedDestinationCluster); i { case 0: return &v.state case 1: @@ -2371,7 +2423,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LBPolicyLeastRequest); i { + switch v := v.(*DynamicEndpointGroupConfig); i { case 0: return &v.state case 1: @@ -2383,7 +2435,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LBPolicyRoundRobin); i { + switch v := v.(*LBPolicyLeastRequest); i { case 0: return &v.state case 1: @@ -2395,7 +2447,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LBPolicyRandom); i { + switch v := v.(*LBPolicyRoundRobin); i { case 0: return &v.state case 1: @@ -2407,7 +2459,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LBPolicyRingHash); i { + switch v := v.(*LBPolicyRandom); i { case 0: return &v.state case 1: @@ -2419,7 +2471,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LBPolicyMaglev); i { + switch v := v.(*LBPolicyRingHash); i { case 0: return &v.state case 1: @@ -2431,7 +2483,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CircuitBreakers); i { + switch v := v.(*LBPolicyMaglev); i { case 0: return &v.state case 1: @@ -2443,7 +2495,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpstreamLimits); i { + switch v := v.(*CircuitBreakers); i { case 0: return &v.state case 1: @@ -2455,7 +2507,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OutlierDetection); i { + switch v := v.(*UpstreamLimits); i { case 0: return &v.state case 1: @@ -2467,7 +2519,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpstreamConnectionOptions); i { + switch v := v.(*OutlierDetection); i { case 0: return &v.state case 1: @@ -2479,7 +2531,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PassthroughEndpointGroupConfig); i { + switch v := v.(*UpstreamConnectionOptions); i { case 0: return &v.state case 1: @@ -2491,7 +2543,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DNSEndpointGroupConfig); i { + switch v := v.(*PassthroughEndpointGroupConfig); i { case 0: return &v.state case 1: @@ -2503,6 +2555,18 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { } } file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DNSEndpointGroupConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StaticEndpointGroupConfig); i { case 0: return &v.state @@ -2525,7 +2589,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { (*EndpointGroup_Dns)(nil), (*EndpointGroup_Passthrough)(nil), } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[12].OneofWrappers = []interface{}{ + file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[13].OneofWrappers = []interface{}{ (*DynamicEndpointGroupConfig_LeastRequest)(nil), (*DynamicEndpointGroupConfig_RoundRobin)(nil), (*DynamicEndpointGroupConfig_Random)(nil), @@ -2538,7 +2602,7 @@ func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDesc, NumEnums: 1, - NumMessages: 25, + NumMessages: 26, NumExtensions: 0, NumServices: 0, }, diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.proto b/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.proto index 802e873401e8..93008c4b04ec 100644 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.proto +++ b/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.proto @@ -77,6 +77,11 @@ message StaticEndpointGroup { StaticEndpointGroupConfig config = 1; } +message DestinationCluster { + // name is the name of the cluster. This will be used to look up a cluster in the clusters map. + string name = 1; +} + message L4WeightedClusterGroup { // clusters to route to by weight. repeated L4WeightedDestinationCluster clusters = 1; diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/listener.pb.go b/proto-public/pbmesh/v1alpha1/pbproxystate/listener.pb.go index 8a4790f10b0f..b50d47d74600 100644 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/listener.pb.go +++ b/proto-public/pbmesh/v1alpha1/pbproxystate/listener.pb.go @@ -635,12 +635,17 @@ type L4Destination struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // name is a key in the top level clusters map. This specifies which cluster to go to in this L4 destination. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // destination is one or more clusters to route to. + // + // Types that are assignable to Destination: + // + // *L4Destination_Cluster + // *L4Destination_WeightedClusters + Destination isL4Destination_Destination `protobuf_oneof:"destination"` // stat_prefix is for compatibility with v1 xds configuration, so it is generated in exactly the same way. - StatPrefix string `protobuf:"bytes,2,opt,name=stat_prefix,json=statPrefix,proto3" json:"stat_prefix,omitempty"` + StatPrefix string `protobuf:"bytes,3,opt,name=stat_prefix,json=statPrefix,proto3" json:"stat_prefix,omitempty"` // traffic_permissions is a list of traffic permissions for this destination. - TrafficPermissions *L4TrafficPermissions `protobuf:"bytes,3,opt,name=traffic_permissions,json=trafficPermissions,proto3" json:"traffic_permissions,omitempty"` + TrafficPermissions *L4TrafficPermissions `protobuf:"bytes,4,opt,name=traffic_permissions,json=trafficPermissions,proto3" json:"traffic_permissions,omitempty"` // max_inbound_connections specifies how many connections this destination can accept. MaxInboundConnections uint64 `protobuf:"varint,5,opt,name=max_inbound_connections,json=maxInboundConnections,proto3" json:"max_inbound_connections,omitempty"` } @@ -677,11 +682,25 @@ func (*L4Destination) Descriptor() ([]byte, []int) { return file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescGZIP(), []int{4} } -func (x *L4Destination) GetName() string { - if x != nil { - return x.Name +func (m *L4Destination) GetDestination() isL4Destination_Destination { + if m != nil { + return m.Destination } - return "" + return nil +} + +func (x *L4Destination) GetCluster() *DestinationCluster { + if x, ok := x.GetDestination().(*L4Destination_Cluster); ok { + return x.Cluster + } + return nil +} + +func (x *L4Destination) GetWeightedClusters() *L4WeightedClusterGroup { + if x, ok := x.GetDestination().(*L4Destination_WeightedClusters); ok { + return x.WeightedClusters + } + return nil } func (x *L4Destination) GetStatPrefix() string { @@ -705,6 +724,22 @@ func (x *L4Destination) GetMaxInboundConnections() uint64 { return 0 } +type isL4Destination_Destination interface { + isL4Destination_Destination() +} + +type L4Destination_Cluster struct { + Cluster *DestinationCluster `protobuf:"bytes,1,opt,name=cluster,proto3,oneof"` +} + +type L4Destination_WeightedClusters struct { + WeightedClusters *L4WeightedClusterGroup `protobuf:"bytes,2,opt,name=weighted_clusters,json=weightedClusters,proto3,oneof"` +} + +func (*L4Destination_Cluster) isL4Destination_Destination() {} + +func (*L4Destination_WeightedClusters) isL4Destination_Destination() {} + type L7Destination struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -869,209 +904,225 @@ var file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDesc = []byte{ 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x70, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x33, - 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0xab, 0x06, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x54, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x74, 0x61, 0x74, 0x65, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x1a, 0x36, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x2f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x33, 0x70, 0x62, 0x6d, 0x65, + 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, + 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, + 0x72, 0x74, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, + 0xab, 0x06, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x54, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, + 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, + 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x50, + 0x6f, 0x72, 0x74, 0x12, 0x61, 0x0a, 0x0b, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x73, 0x6f, 0x63, 0x6b, + 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, + 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, + 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x0a, 0x75, 0x6e, 0x69, 0x78, + 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x4d, 0x0a, 0x07, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, + 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x09, 0x68, 0x6f, - 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x07, 0x72, 0x6f, + 0x75, 0x74, 0x65, 0x72, 0x73, 0x12, 0x5a, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, + 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, 0x6f, 0x73, 0x74, - 0x50, 0x6f, 0x72, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x08, 0x68, - 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x61, 0x0a, 0x0b, 0x75, 0x6e, 0x69, 0x78, 0x5f, - 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x53, - 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x0a, - 0x75, 0x6e, 0x69, 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x4d, 0x0a, 0x07, 0x72, 0x6f, - 0x75, 0x74, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, - 0x52, 0x07, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x73, 0x12, 0x5a, 0x0a, 0x0e, 0x64, 0x65, 0x66, - 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x72, 0x12, 0x5b, 0x0a, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, - 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x37, 0x2e, 0x68, 0x61, + 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x72, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x72, 0x12, 0x5b, 0x0a, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, + 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, + 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x70, + 0x0a, 0x13, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, - 0x65, 0x73, 0x12, 0x70, 0x0a, 0x13, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x61, + 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x12, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x12, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x5f, 0x68, - 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x13, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x48, 0x61, 0x74, 0x63, 0x68, - 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x18, 0x75, 0x73, 0x65, 0x5f, - 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x5f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x74, 0x72, 0x61, - 0x63, 0x69, 0x6e, 0x67, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x75, 0x73, 0x65, 0x45, - 0x73, 0x63, 0x61, 0x70, 0x65, 0x48, 0x61, 0x74, 0x63, 0x68, 0x54, 0x72, 0x61, 0x63, 0x69, 0x6e, - 0x67, 0x42, 0x0e, 0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x22, 0xad, 0x03, 0x0a, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x05, - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, + 0x12, 0x32, 0x0a, 0x15, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x5f, 0x68, 0x61, 0x74, 0x63, 0x68, + 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x13, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x48, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x69, 0x73, 0x74, + 0x65, 0x6e, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x18, 0x75, 0x73, 0x65, 0x5f, 0x65, 0x73, 0x63, 0x61, + 0x70, 0x65, 0x5f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x75, 0x73, 0x65, 0x45, 0x73, 0x63, 0x61, 0x70, + 0x65, 0x48, 0x61, 0x74, 0x63, 0x68, 0x54, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x42, 0x0e, 0x0a, + 0x0c, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xad, 0x03, + 0x0a, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, + 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x05, 0x6d, 0x61, 0x74, + 0x63, 0x68, 0x12, 0x4c, 0x0a, 0x02, 0x6c, 0x34, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x34, 0x44, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x02, 0x6c, 0x34, + 0x12, 0x4c, 0x0a, 0x02, 0x6c, 0x37, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, + 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x37, 0x44, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x02, 0x6c, 0x37, 0x12, 0x4f, + 0x0a, 0x03, 0x73, 0x6e, 0x69, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, - 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x4c, 0x0a, 0x02, 0x6c, 0x34, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x4c, 0x34, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, - 0x52, 0x02, 0x6c, 0x34, 0x12, 0x4c, 0x0a, 0x02, 0x6c, 0x37, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, - 0x37, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x02, - 0x6c, 0x37, 0x12, 0x4f, 0x0a, 0x03, 0x73, 0x6e, 0x69, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x4e, - 0x49, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x03, - 0x73, 0x6e, 0x69, 0x12, 0x5d, 0x0a, 0x0b, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, - 0x6c, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, - 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, - 0x6c, 0x73, 0x42, 0x0d, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x22, 0xe1, 0x02, 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x61, - 0x6c, 0x70, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x6c, 0x70, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x73, 0x12, 0x47, 0x0a, 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x5b, 0x0a, 0x0d, 0x70, - 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x4e, 0x49, 0x44, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x03, 0x73, 0x6e, 0x69, 0x12, + 0x5d, 0x0a, 0x0b, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x6c, 0x73, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x6f, 0x63, 0x6b, + 0x65, 0x74, 0x52, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x6c, 0x73, 0x42, 0x0d, + 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xe1, 0x02, + 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x70, 0x6e, 0x5f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0d, 0x61, 0x6c, 0x70, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x12, 0x47, + 0x0a, 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, + 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, + 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x5b, 0x0a, 0x0d, 0x70, 0x72, 0x65, 0x66, 0x69, + 0x78, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x69, 0x64, + 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x61, + 0x6e, 0x67, 0x65, 0x73, 0x12, 0x68, 0x0a, 0x14, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x66, - 0x69, 0x78, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x68, 0x0a, 0x14, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x12, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x61, 0x6e, 0x67, - 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x6f, 0x0a, 0x09, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, - 0x67, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x70, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x3b, 0x0a, 0x0a, 0x70, 0x72, 0x65, - 0x66, 0x69, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x09, 0x70, 0x72, 0x65, - 0x66, 0x69, 0x78, 0x4c, 0x65, 0x6e, 0x22, 0xf0, 0x01, 0x0a, 0x0d, 0x4c, 0x34, 0x44, 0x65, 0x73, - 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, - 0x73, 0x74, 0x61, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x72, 0x0a, + 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x12, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x21, + 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x22, 0x6f, 0x0a, 0x09, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x25, + 0x0a, 0x0e, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x3b, 0x0a, 0x0a, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, + 0x6c, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, + 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x09, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x4c, + 0x65, 0x6e, 0x22, 0xbc, 0x03, 0x0a, 0x0d, 0x4c, 0x34, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x12, 0x72, 0x0a, 0x11, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, + 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x34, 0x57, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x48, 0x00, 0x52, 0x10, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x70, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, + 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x72, 0x0a, 0x13, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, + 0x63, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x2e, 0x4c, 0x34, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x12, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x6d, 0x61, + 0x78, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x6d, 0x61, 0x78, + 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x42, 0x0d, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x22, 0x8b, 0x03, 0x0a, 0x0d, 0x4c, 0x37, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x5f, + 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, + 0x61, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x53, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, + 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, + 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x37, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x72, 0x0a, 0x13, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x34, 0x54, 0x72, 0x61, 0x66, 0x66, + 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x37, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x12, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x36, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x15, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x8b, 0x03, 0x0a, 0x0d, 0x4c, 0x37, - 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, - 0x12, 0x53, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x4c, 0x37, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x72, 0x0a, 0x13, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, - 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x4c, 0x37, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x12, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x63, - 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x78, 0x66, 0x63, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0b, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x58, 0x66, 0x63, 0x63, 0x12, 0x21, 0x0a, 0x0c, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, - 0x36, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x15, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x31, 0x0a, 0x0e, 0x53, 0x4e, 0x49, 0x44, 0x65, - 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, - 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x73, 0x74, 0x61, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x2a, 0x55, 0x0a, 0x09, 0x44, 0x69, - 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x49, 0x52, 0x45, 0x43, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x49, 0x52, - 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, 0x55, 0x54, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x10, - 0x02, 0x2a, 0x54, 0x0a, 0x12, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x42, 0x41, 0x4c, 0x41, 0x4e, - 0x43, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x44, - 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x42, 0x41, 0x4c, 0x41, - 0x4e, 0x43, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, - 0x45, 0x58, 0x41, 0x43, 0x54, 0x10, 0x01, 0x2a, 0x71, 0x0a, 0x0a, 0x43, 0x61, 0x70, 0x61, 0x62, - 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x41, 0x50, 0x41, 0x42, 0x49, 0x4c, - 0x49, 0x54, 0x59, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x50, 0x41, 0x52, 0x45, 0x4e, 0x54, 0x10, - 0x00, 0x12, 0x25, 0x0a, 0x21, 0x43, 0x41, 0x50, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, - 0x4c, 0x37, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x43, 0x41, 0x50, 0x41, - 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x4c, 0x34, 0x5f, 0x54, 0x4c, 0x53, 0x5f, 0x49, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x2a, 0x4f, 0x0a, 0x0a, 0x4c, 0x37, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x37, 0x5f, 0x50, - 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x15, - 0x0a, 0x11, 0x4c, 0x37, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x48, 0x54, - 0x54, 0x50, 0x32, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x37, 0x5f, 0x50, 0x52, 0x4f, 0x54, - 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x47, 0x52, 0x50, 0x43, 0x10, 0x02, 0x42, 0xd9, 0x02, 0x0a, 0x2f, - 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, - 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x45, 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, 0x6d, 0x65, 0x73, - 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, - 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2b, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x37, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, - 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2f, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, - 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x78, 0x66, 0x63, + 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x58, 0x66, 0x63, 0x63, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x63, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x69, + 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, + 0x31, 0x0a, 0x0e, 0x53, 0x4e, 0x49, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x2a, 0x55, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x19, 0x0a, 0x15, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x49, + 0x52, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x10, + 0x01, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, + 0x55, 0x54, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x2a, 0x54, 0x0a, 0x12, 0x42, 0x61, 0x6c, + 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x1f, 0x0a, 0x1b, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, + 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, + 0x12, 0x1d, 0x0a, 0x19, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, + 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x45, 0x58, 0x41, 0x43, 0x54, 0x10, 0x01, 0x2a, + 0x71, 0x0a, 0x0a, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, + 0x16, 0x43, 0x41, 0x50, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x54, 0x52, 0x41, 0x4e, + 0x53, 0x50, 0x41, 0x52, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x25, 0x0a, 0x21, 0x43, 0x41, 0x50, + 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x4c, 0x37, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, + 0x43, 0x4f, 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, + 0x12, 0x20, 0x0a, 0x1c, 0x43, 0x41, 0x50, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x4c, + 0x34, 0x5f, 0x54, 0x4c, 0x53, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, + 0x10, 0x02, 0x2a, 0x4f, 0x0a, 0x0a, 0x4c, 0x37, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x37, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, + 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x4c, 0x37, 0x5f, 0x50, 0x52, 0x4f, + 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x48, 0x54, 0x54, 0x50, 0x32, 0x10, 0x01, 0x12, 0x14, 0x0a, + 0x10, 0x4c, 0x37, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x47, 0x52, 0x50, + 0x43, 0x10, 0x02, 0x42, 0xd9, 0x02, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, + 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, + 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, + 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, + 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, + 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, + 0x61, 0x74, 0x65, 0xe2, 0x02, 0x37, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2f, + 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1104,8 +1155,10 @@ var file_pbmesh_v1alpha1_pbproxystate_listener_proto_goTypes = []interface{}{ (*UnixSocketAddress)(nil), // 12: hashicorp.consul.mesh.v1alpha1.pbproxystate.UnixSocketAddress (*TransportSocket)(nil), // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket (*wrapperspb.UInt32Value)(nil), // 14: google.protobuf.UInt32Value - (*L4TrafficPermissions)(nil), // 15: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4TrafficPermissions - (*L7TrafficPermissions)(nil), // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7TrafficPermissions + (*DestinationCluster)(nil), // 15: hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationCluster + (*L4WeightedClusterGroup)(nil), // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedClusterGroup + (*L4TrafficPermissions)(nil), // 17: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4TrafficPermissions + (*L7TrafficPermissions)(nil), // 18: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7TrafficPermissions } var file_pbmesh_v1alpha1_pbproxystate_listener_proto_depIdxs = []int32{ 0, // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.Listener.direction:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.Direction @@ -1124,14 +1177,16 @@ var file_pbmesh_v1alpha1_pbproxystate_listener_proto_depIdxs = []int32{ 7, // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.Match.prefix_ranges:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.CidrRange 7, // 14: hashicorp.consul.mesh.v1alpha1.pbproxystate.Match.source_prefix_ranges:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.CidrRange 14, // 15: hashicorp.consul.mesh.v1alpha1.pbproxystate.CidrRange.prefix_len:type_name -> google.protobuf.UInt32Value - 15, // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4Destination.traffic_permissions:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L4TrafficPermissions - 3, // 17: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Destination.protocol:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Protocol - 16, // 18: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Destination.traffic_permissions:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L7TrafficPermissions - 19, // [19:19] is the sub-list for method output_type - 19, // [19:19] is the sub-list for method input_type - 19, // [19:19] is the sub-list for extension type_name - 19, // [19:19] is the sub-list for extension extendee - 0, // [0:19] is the sub-list for field type_name + 15, // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4Destination.cluster:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationCluster + 16, // 17: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4Destination.weighted_clusters:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedClusterGroup + 17, // 18: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4Destination.traffic_permissions:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L4TrafficPermissions + 3, // 19: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Destination.protocol:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Protocol + 18, // 20: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Destination.traffic_permissions:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L7TrafficPermissions + 21, // [21:21] is the sub-list for method output_type + 21, // [21:21] is the sub-list for method input_type + 21, // [21:21] is the sub-list for extension type_name + 21, // [21:21] is the sub-list for extension extendee + 0, // [0:21] is the sub-list for field type_name } func init() { file_pbmesh_v1alpha1_pbproxystate_listener_proto_init() } @@ -1140,6 +1195,7 @@ func file_pbmesh_v1alpha1_pbproxystate_listener_proto_init() { return } file_pbmesh_v1alpha1_pbproxystate_address_proto_init() + file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() file_pbmesh_v1alpha1_pbproxystate_traffic_permissions_proto_init() file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_init() if !protoimpl.UnsafeEnabled { @@ -1237,6 +1293,10 @@ func file_pbmesh_v1alpha1_pbproxystate_listener_proto_init() { (*Router_L7)(nil), (*Router_Sni)(nil), } + file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[4].OneofWrappers = []interface{}{ + (*L4Destination_Cluster)(nil), + (*L4Destination_WeightedClusters)(nil), + } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/listener.proto b/proto-public/pbmesh/v1alpha1/pbproxystate/listener.proto index 7b851ea7a992..0582197638f0 100644 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/listener.proto +++ b/proto-public/pbmesh/v1alpha1/pbproxystate/listener.proto @@ -7,6 +7,7 @@ package hashicorp.consul.mesh.v1alpha1.pbproxystate; import "google/protobuf/wrappers.proto"; import "pbmesh/v1alpha1/pbproxystate/address.proto"; +import "pbmesh/v1alpha1/pbproxystate/cluster.proto"; import "pbmesh/v1alpha1/pbproxystate/traffic_permissions.proto"; import "pbmesh/v1alpha1/pbproxystate/transport_socket.proto"; @@ -88,12 +89,15 @@ message CidrRange { } message L4Destination { - // name is a key in the top level clusters map. This specifies which cluster to go to in this L4 destination. - string name = 1; + // destination is one or more clusters to route to. + oneof destination { + DestinationCluster cluster = 1; + L4WeightedClusterGroup weighted_clusters = 2; + } // stat_prefix is for compatibility with v1 xds configuration, so it is generated in exactly the same way. - string stat_prefix = 2; + string stat_prefix = 3; // traffic_permissions is a list of traffic permissions for this destination. - L4TrafficPermissions traffic_permissions = 3; + L4TrafficPermissions traffic_permissions = 4; // max_inbound_connections specifies how many connections this destination can accept. uint64 max_inbound_connections = 5; } diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.binary.go b/proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.binary.go index 5d6ba14ecc91..df9142573e3d 100644 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.binary.go +++ b/proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.binary.go @@ -166,13 +166,3 @@ func (msg *ConnectionPropertiesPolicy) MarshalBinary() ([]byte, error) { func (msg *ConnectionPropertiesPolicy) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DestinationCluster) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DestinationCluster) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.go b/proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.go index c6840dd18aaa..46def51450e6 100644 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.go +++ b/proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.go @@ -1258,54 +1258,6 @@ func (x *ConnectionPropertiesPolicy) GetTerminal() bool { return false } -type DestinationCluster struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name is the name of the cluster. This will be used to look up a cluster in the clusters map. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` -} - -func (x *DestinationCluster) Reset() { - *x = DestinationCluster{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DestinationCluster) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DestinationCluster) ProtoMessage() {} - -func (x *DestinationCluster) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DestinationCluster.ProtoReflect.Descriptor instead. -func (*DestinationCluster) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{16} -} - -func (x *DestinationCluster) GetName() string { - if x != nil { - return x.Name - } - return "" -} - var File_pbmesh_v1alpha1_pbproxystate_route_proto protoreflect.FileDescriptor var file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDesc = []byte{ @@ -1534,31 +1486,29 @@ var file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDesc = []byte{ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x65, 0x72, 0x6d, - 0x69, 0x6e, 0x61, 0x6c, 0x22, 0x28, 0x0a, 0x12, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0xd6, - 0x02, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x42, 0x0a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x45, 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, 0x6d, 0x65, 0x73, - 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, - 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2b, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x37, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, - 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2f, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, - 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x6e, 0x61, 0x6c, 0x42, 0xd6, 0x02, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, + 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, + 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, + 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, + 0x61, 0x74, 0x65, 0xca, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, + 0x65, 0xe2, 0x02, 0x37, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, + 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2f, 0x48, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, + 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3a, + 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1573,7 +1523,7 @@ func file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP() []byte { return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescData } -var file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes = make([]protoimpl.MessageInfo, 17) +var file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes = make([]protoimpl.MessageInfo, 16) var file_pbmesh_v1alpha1_pbproxystate_route_proto_goTypes = []interface{}{ (*Route)(nil), // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.Route (*VirtualHost)(nil), // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.VirtualHost @@ -1591,8 +1541,8 @@ var file_pbmesh_v1alpha1_pbproxystate_route_proto_goTypes = []interface{}{ (*HeaderPolicy)(nil), // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderPolicy (*QueryParameterPolicy)(nil), // 14: hashicorp.consul.mesh.v1alpha1.pbproxystate.QueryParameterPolicy (*ConnectionPropertiesPolicy)(nil), // 15: hashicorp.consul.mesh.v1alpha1.pbproxystate.ConnectionPropertiesPolicy - (*DestinationCluster)(nil), // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationCluster - (*HeaderMutation)(nil), // 17: hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation + (*HeaderMutation)(nil), // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation + (*DestinationCluster)(nil), // 17: hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationCluster (*L7WeightedClusterGroup)(nil), // 18: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedClusterGroup (*wrapperspb.BoolValue)(nil), // 19: google.protobuf.BoolValue (*wrapperspb.UInt32Value)(nil), // 20: google.protobuf.UInt32Value @@ -1600,15 +1550,15 @@ var file_pbmesh_v1alpha1_pbproxystate_route_proto_goTypes = []interface{}{ } var file_pbmesh_v1alpha1_pbproxystate_route_proto_depIdxs = []int32{ 1, // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.Route.virtual_hosts:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.VirtualHost - 17, // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.VirtualHost.header_mutations:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation + 16, // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.VirtualHost.header_mutations:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation 2, // 2: hashicorp.consul.mesh.v1alpha1.pbproxystate.VirtualHost.route_rules:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteRule 3, // 3: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteRule.match:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteMatch 7, // 4: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteRule.destination:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteDestination - 17, // 5: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteRule.header_mutations:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation + 16, // 5: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteRule.header_mutations:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation 4, // 6: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteMatch.path_match:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.PathMatch 6, // 7: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteMatch.header_matches:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMatch 5, // 8: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteMatch.query_parameter_matches:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.QueryParameterMatch - 16, // 9: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteDestination.cluster:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationCluster + 17, // 9: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteDestination.cluster:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationCluster 18, // 10: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteDestination.weighted_clusters:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedClusterGroup 8, // 11: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteDestination.destination_configuration:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationConfiguration 19, // 12: hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationConfiguration.auto_host_rewrite:type_name -> google.protobuf.BoolValue @@ -1830,18 +1780,6 @@ func file_pbmesh_v1alpha1_pbproxystate_route_proto_init() { return nil } } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationCluster); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } } file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[4].OneofWrappers = []interface{}{ (*PathMatch_Exact)(nil), @@ -1876,7 +1814,7 @@ func file_pbmesh_v1alpha1_pbproxystate_route_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDesc, NumEnums: 0, - NumMessages: 17, + NumMessages: 16, NumExtensions: 0, NumServices: 0, }, diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/route.proto b/proto-public/pbmesh/v1alpha1/pbproxystate/route.proto index 2ec10f3737d1..c702bec88fb9 100644 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/route.proto +++ b/proto-public/pbmesh/v1alpha1/pbproxystate/route.proto @@ -129,8 +129,3 @@ message ConnectionPropertiesPolicy { bool source_ip = 1; bool terminal = 2; } - -message DestinationCluster { - // name is the name of the cluster. This will be used to look up a cluster in the clusters map. - string name = 1; -} diff --git a/website/content/docs/api-gateway/configuration/gatewayclassconfig.mdx b/website/content/docs/api-gateway/configuration/gatewayclassconfig.mdx index ea3357deceef..2fa35a75521e 100644 --- a/website/content/docs/api-gateway/configuration/gatewayclassconfig.mdx +++ b/website/content/docs/api-gateway/configuration/gatewayclassconfig.mdx @@ -38,7 +38,9 @@ The following outline shows how to format the configurations in the `GatewayClas * [`consulAPIGateway`](#image-consulapigateway): string | optional * [`envoy`](#image-envoy): string | optional * [`logLevel`](#loglevel): string | optional +* [`matchPrivilegedContainerPorts`](#matchPrivilegedContainerPorts): integer | optional * [`nodeSelector`](#nodeselector): string | optional +* [`openshiftSCCName`](#openshiftSCCName): string | optional * [`serviceType`](#servicetype): string | optional * [`useHostPorts`](#usehostports): boolean | optional @@ -152,12 +154,26 @@ You can specify the following strings: * `debug` * `trace` +### matchPrivilegedContainerPorts +Specifies a value that Consul adds to privileged ports defined in the gateway. Privileged ports are port numbers less than 1024 and some platforms, such as Red Hat OpenShift, explicitly configure Kubernetes to avoid running containers on privileged ports. The total value of the configured port number and the `matchPriviledgedContainerPorts` value must not exceed 65535, which is the highest possible TCP port number allowed. +for gateway containers +* Type: Integer +* Required: optional + +You can specify an integer between `0` and `64512` + ### nodeSelector Pods normally run on multiple nodes. You can specify a set of parameters in the `nodeSelector` that constrain the nodes on which the pod can run, enabling the pod to fit on a node. The selector must match a node's labels for the pod to be scheduled on that node. Refer to the [Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) for additional information. * Type: string * Required: optional +### openshiftSCCName +Specifies the OpenShift security context constraint (SCC) for the `GatewayClassConfig` to use. Refer to the [OpenShift SCC documentation](https://docs.openshift.com/container-platform/4.13/authentication/managing-security-context-constraints.html#default-sccs_configuring-internal-oauth) for additional information about the available default SCCs. +* Type: string +* Required: optional +* Default: `restricted-v2` + ### serviceType Specifies the ingress methods for the gateway's Kubernetes service. * Type: string