resource: Require scope for resource registration (#18635)

This commit is contained in:
Semir Patel 2023-09-01 09:44:53 -05:00 committed by GitHub
parent 13eefbb840
commit b96cff7436
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 212 additions and 103 deletions

View File

@ -7,6 +7,7 @@ import (
"context"
"testing"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
@ -16,6 +17,7 @@ import (
"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/acl/resolver"
svc "github.com/hashicorp/consul/agent/grpc-external/services/resource"
"github.com/hashicorp/consul/agent/grpc-external/testutils"
internal "github.com/hashicorp/consul/agent/grpc-internal"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/internal/resource"
@ -52,7 +54,27 @@ func AuthorizerFrom(t *testing.T, policyStrs ...string) resolver.Result {
// returns a client to interact with it. ACLs will be disabled and only the
// default partition and namespace are available.
func RunResourceService(t *testing.T, registerFns ...func(resource.Registry)) pbresource.ResourceServiceClient {
return RunResourceServiceWithACL(t, resolver.DANGER_NO_AUTH{}, registerFns...)
// Provide a resolver which will default partition and namespace when not provided. This is similar to user
// initiated requests.
//
// Controllers under test should be providing full tenancy since they will run with the DANGER_NO_AUTH.
mockACLResolver := &svc.MockACLResolver{}
mockACLResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything).
Return(testutils.ACLsDisabled(t), nil).
Run(func(args mock.Arguments) {
// Caller expecting passed in tokenEntMeta and authorizerContext to be filled in.
tokenEntMeta := args.Get(1).(*acl.EnterpriseMeta)
if tokenEntMeta != nil {
FillEntMeta(tokenEntMeta)
}
authzContext := args.Get(2).(*acl.AuthorizerContext)
if authzContext != nil {
FillAuthorizerContext(authzContext)
}
})
return RunResourceServiceWithACL(t, mockACLResolver, registerFns...)
}
func RunResourceServiceWithACL(t *testing.T, aclResolver svc.ACLResolver, registerFns ...func(resource.Registry)) pbresource.ResourceServiceClient {

View File

@ -0,0 +1,19 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
//go:build !consulent
// +build !consulent
package testing
import (
"github.com/hashicorp/consul/acl"
)
func FillEntMeta(entMeta *acl.EnterpriseMeta) {
// nothing to to in CE.
}
func FillAuthorizerContext(authzContext *acl.AuthorizerContext) {
// nothing to to in CE.
}

View File

@ -13,6 +13,7 @@ import (
"github.com/hashicorp/consul/internal/catalog/internal/controllers/nodehealth"
"github.com/hashicorp/consul/internal/catalog/internal/controllers/workloadhealth"
"github.com/hashicorp/consul/internal/catalog/internal/types"
"github.com/hashicorp/consul/internal/resource"
rtest "github.com/hashicorp/consul/internal/resource/resourcetest"
pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1"
"github.com/hashicorp/consul/proto-public/pbresource"
@ -68,7 +69,7 @@ func VerifyCatalogV1Alpha1IntegrationTestResults(t *testing.T, client pbresource
c.RequireResourceExists(t, rtest.Resource(catalog.ServiceV1Alpha1Type, "foo").ID())
for i := 1; i < 5; i++ {
nodeId := rtest.Resource(catalog.NodeV1Alpha1Type, fmt.Sprintf("node-%d", i)).ID()
nodeId := rtest.Resource(catalog.NodeV1Alpha1Type, fmt.Sprintf("node-%d", i)).WithTenancy(resource.DefaultNamespacedTenancy()).ID()
c.RequireResourceExists(t, nodeId)
res := c.RequireResourceExists(t, rtest.Resource(catalog.HealthStatusV1Alpha1Type, fmt.Sprintf("node-%d-health", i)).ID())
@ -76,7 +77,7 @@ func VerifyCatalogV1Alpha1IntegrationTestResults(t *testing.T, client pbresource
}
for i := 1; i < 21; i++ {
workloadId := rtest.Resource(catalog.WorkloadV1Alpha1Type, fmt.Sprintf("api-%d", i)).ID()
workloadId := rtest.Resource(catalog.WorkloadV1Alpha1Type, fmt.Sprintf("api-%d", i)).WithTenancy(resource.DefaultNamespacedTenancy()).ID()
c.RequireResourceExists(t, workloadId)
res := c.RequireResourceExists(t, rtest.Resource(catalog.HealthStatusV1Alpha1Type, fmt.Sprintf("api-%d-health", i)).ID())

View File

@ -695,7 +695,6 @@ func RunCatalogV1Alpha1EndpointsLifecycleIntegrationTest(t *testing.T, client pb
// Now delete the service and ensure that the endpoints eventually are deleted as well
c.MustDelete(t, service.Id)
c.WaitForDeletion(t, endpointsID)
}
func setHealthStatus(t *testing.T, client *rtest.Client, owner *pbresource.ID, name string, health pbcatalog.Health) *pbresource.Resource {

View File

@ -130,7 +130,7 @@ func (suite *reconciliationDataSuite) SetupTest() {
WithData(suite.T(), &pbcatalog.ServiceEndpoints{
Endpoints: []*pbcatalog.Endpoint{
{
TargetRef: rtest.Resource(types.WorkloadType, "api-1").ID(),
TargetRef: rtest.Resource(types.WorkloadType, "api-1").WithTenancy(resource.DefaultNamespacedTenancy()).ID(),
Addresses: []*pbcatalog.WorkloadAddress{
{
Host: "127.0.0.1",
@ -150,7 +150,7 @@ func (suite *reconciliationDataSuite) SetupTest() {
func (suite *reconciliationDataSuite) TestGetServiceData_NotFound() {
// This test's purposes is to ensure that NotFound errors when retrieving
// the service data are ignored properly.
data, err := getServiceData(suite.ctx, suite.rt, rtest.Resource(types.ServiceType, "not-found").ID())
data, err := getServiceData(suite.ctx, suite.rt, rtest.Resource(types.ServiceType, "not-found").WithTenancy(resource.DefaultNamespacedTenancy()).ID())
require.NoError(suite.T(), err)
require.Nil(suite.T(), data)
}

View File

@ -54,8 +54,8 @@ func (suite *controllerSuite) TestController() {
go mgr.Run(suite.ctx)
// Create an advance pointer to some services.
apiServiceRef := resource.Reference(rtest.Resource(types.ServiceType, "api").ID(), "")
otherServiceRef := resource.Reference(rtest.Resource(types.ServiceType, "other").ID(), "")
apiServiceRef := resource.Reference(rtest.Resource(types.ServiceType, "api").WithTenancy(resource.DefaultNamespacedTenancy()).ID(), "")
otherServiceRef := resource.Reference(rtest.Resource(types.ServiceType, "other").WithTenancy(resource.DefaultNamespacedTenancy()).ID(), "")
// create a failover without any services
failoverData := &pbcatalog.FailoverPolicy{

View File

@ -24,31 +24,37 @@ func TestMapper_Tracking(t *testing.T) {
// Create an advance pointer to some services.
randoSvc := rtest.Resource(types.ServiceType, "rando").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(t, &pbcatalog.Service{}).
Build()
rtest.ValidateAndNormalize(t, registry, randoSvc)
apiSvc := rtest.Resource(types.ServiceType, "api").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(t, &pbcatalog.Service{}).
Build()
rtest.ValidateAndNormalize(t, registry, apiSvc)
fooSvc := rtest.Resource(types.ServiceType, "foo").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(t, &pbcatalog.Service{}).
Build()
rtest.ValidateAndNormalize(t, registry, fooSvc)
barSvc := rtest.Resource(types.ServiceType, "bar").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(t, &pbcatalog.Service{}).
Build()
rtest.ValidateAndNormalize(t, registry, barSvc)
wwwSvc := rtest.Resource(types.ServiceType, "www").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(t, &pbcatalog.Service{}).
Build()
rtest.ValidateAndNormalize(t, registry, wwwSvc)
fail1 := rtest.Resource(types.FailoverPolicyType, "api").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(t, &pbcatalog.FailoverPolicy{
Config: &pbcatalog.FailoverConfig{
Destinations: []*pbcatalog.FailoverDestination{
@ -62,6 +68,7 @@ func TestMapper_Tracking(t *testing.T) {
failDec1 := rtest.MustDecode[*pbcatalog.FailoverPolicy](t, fail1)
fail2 := rtest.Resource(types.FailoverPolicyType, "www").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(t, &pbcatalog.FailoverPolicy{
Config: &pbcatalog.FailoverConfig{
Destinations: []*pbcatalog.FailoverDestination{
@ -75,6 +82,7 @@ func TestMapper_Tracking(t *testing.T) {
failDec2 := rtest.MustDecode[*pbcatalog.FailoverPolicy](t, fail2)
fail1_updated := rtest.Resource(types.FailoverPolicyType, "api").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(t, &pbcatalog.FailoverPolicy{
Config: &pbcatalog.FailoverConfig{
Destinations: []*pbcatalog.FailoverDestination{
@ -178,13 +186,7 @@ func requireServicesTracked(t *testing.T, mapper *Mapper, svc *pbresource.Resour
}
func newRef(typ *pbresource.Type, name string) *pbresource.Reference {
return rtest.Resource(typ, name).Reference("")
}
func defaultTenancy() *pbresource.Tenancy {
return &pbresource.Tenancy{
Partition: "default",
Namespace: "default",
PeerName: "local",
}
return rtest.Resource(typ, name).
WithTenancy(resource.DefaultNamespacedTenancy()).
Reference("")
}

View File

@ -30,6 +30,7 @@ func RegisterDNSPolicy(r resource.Registry) {
r.Register(resource.Registration{
Type: DNSPolicyV1Alpha1Type,
Proto: &pbcatalog.DNSPolicy{},
Scope: resource.ScopeNamespace,
Validate: ValidateDNSPolicy,
})
}

View File

@ -33,6 +33,7 @@ func RegisterFailoverPolicy(r resource.Registry) {
r.Register(resource.Registration{
Type: FailoverPolicyV1Alpha1Type,
Proto: &pbcatalog.FailoverPolicy{},
Scope: resource.ScopeNamespace,
Mutate: MutateFailoverPolicy,
Validate: ValidateFailoverPolicy,
})

View File

@ -156,6 +156,7 @@ func TestValidateFailoverPolicy(t *testing.T) {
run := func(t *testing.T, tc testcase) {
res := resourcetest.Resource(FailoverPolicyType, "api").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(t, tc.failover).
Build()
@ -228,7 +229,7 @@ func TestValidateFailoverPolicy(t *testing.T) {
"dest: ref with section": {
config: &pbcatalog.FailoverConfig{
Destinations: []*pbcatalog.FailoverDestination{
{Ref: resourcetest.Resource(ServiceType, "api").Reference("blah")},
{Ref: resourcetest.Resource(ServiceType, "api").WithTenancy(resource.DefaultNamespacedTenancy()).Reference("blah")},
},
},
expectErr: `invalid element at index 0 of list "destinations": invalid "ref" field: invalid "section" field: section not supported for failover policy dest refs`,
@ -589,7 +590,9 @@ func TestSimplifyFailoverPolicy(t *testing.T) {
}
func newRef(typ *pbresource.Type, name string) *pbresource.Reference {
return resourcetest.Resource(typ, name).Reference("")
return resourcetest.Resource(typ, name).
WithTenancy(resource.DefaultNamespacedTenancy()).
Reference("")
}
func newRefWithPeer(typ *pbresource.Type, name string, peer string) *pbresource.Reference {

View File

@ -28,6 +28,7 @@ func RegisterHealthChecks(r resource.Registry) {
r.Register(resource.Registration{
Type: HealthChecksV1Alpha1Type,
Proto: &pbcatalog.HealthChecks{},
Scope: resource.ScopeNamespace,
Validate: ValidateHealthChecks,
})
}

View File

@ -28,6 +28,7 @@ func RegisterHealthStatus(r resource.Registry) {
r.Register(resource.Registration{
Type: HealthStatusV1Alpha1Type,
Proto: &pbcatalog.HealthStatus{},
Scope: resource.ScopeNamespace,
Validate: ValidateHealthStatus,
})
}

View File

@ -26,8 +26,14 @@ var (
func RegisterNode(r resource.Registry) {
r.Register(resource.Registration{
Type: NodeV1Alpha1Type,
Proto: &pbcatalog.Node{},
Type: NodeV1Alpha1Type,
Proto: &pbcatalog.Node{},
// TODO: A node should be partition scoped. However its HealthStatus which is
// namespace scoped has Node as an owner. We do not support ownership between resources
// of differing scope at this time. HealthStatus will probably be split out into two different
// types, one for namespace scoped owners and the other for partition scoped owners.
// Until that time, Node will remain namespace scoped.
Scope: resource.ScopeNamespace,
Validate: ValidateNode,
})
}

View File

@ -31,8 +31,8 @@ func RegisterService(r resource.Registry) {
r.Register(resource.Registration{
Type: ServiceV1Alpha1Type,
Proto: &pbcatalog.Service{},
Validate: ValidateService,
Scope: resource.ScopeNamespace,
Validate: ValidateService,
})
}

View File

@ -31,6 +31,7 @@ func RegisterServiceEndpoints(r resource.Registry) {
r.Register(resource.Registration{
Type: ServiceEndpointsV1Alpha1Type,
Proto: &pbcatalog.ServiceEndpoints{},
Scope: resource.ScopeNamespace,
Validate: ValidateServiceEndpoints,
Mutate: MutateServiceEndpoints,
})

View File

@ -54,6 +54,7 @@ func TestValidateServiceEndpoints_Ok(t *testing.T) {
}
res := rtest.Resource(ServiceEndpointsType, "test-service").
WithTenancy(defaultEndpointTenancy).
WithData(t, data).
Build()
@ -231,6 +232,7 @@ func TestValidateServiceEndpoints_EndpointInvalid(t *testing.T) {
},
}
res := rtest.Resource(ServiceEndpointsType, "test-service").
WithTenancy(defaultEndpointTenancy).
WithOwner(tcase.owner).
WithData(t, data).
Build()
@ -246,7 +248,9 @@ func TestValidateServiceEndpoints_EndpointInvalid(t *testing.T) {
}
func TestMutateServiceEndpoints_PopulateOwner(t *testing.T) {
res := rtest.Resource(ServiceEndpointsType, "test-service").Build()
res := rtest.Resource(ServiceEndpointsType, "test-service").
WithTenancy(defaultEndpointTenancy).
Build()
require.NoError(t, MutateServiceEndpoints(res))
require.NotNil(t, res.Owner)

View File

@ -28,6 +28,7 @@ func RegisterVirtualIPs(r resource.Registry) {
r.Register(resource.Registration{
Type: VirtualIPsV1Alpha1Type,
Proto: &pbcatalog.VirtualIPs{},
Scope: resource.ScopeNamespace,
Validate: ValidateVirtualIPs,
})
}

View File

@ -32,6 +32,7 @@ func RegisterWorkload(r resource.Registry) {
r.Register(resource.Registration{
Type: WorkloadV1Alpha1Type,
Proto: &pbcatalog.Workload{},
Scope: resource.ScopeNamespace,
Validate: ValidateWorkload,
})
}

View File

@ -143,7 +143,7 @@ func (suite *xdsControllerTestSuite) TestReconcile_PushChangeError() {
func (suite *xdsControllerTestSuite) TestReconcile_MissingEndpoint() {
// Set fooProxyStateTemplate with a reference to fooEndpoints, without storing fooEndpoints so the controller should
// notice it's missing.
fooEndpointsId := resourcetest.Resource(catalog.ServiceEndpointsType, "foo-service").ID()
fooEndpointsId := resourcetest.Resource(catalog.ServiceEndpointsType, "foo-service").WithTenancy(resource.DefaultNamespacedTenancy()).ID()
fooRequiredEndpoints := make(map[string]*pbproxystate.EndpointRef)
fooRequiredEndpoints["test-cluster-1"] = &pbproxystate.EndpointRef{
Id: fooEndpointsId,

View File

@ -29,6 +29,7 @@ func RegisterComputedRoutes(r resource.Registry) {
r.Register(resource.Registration{
Type: ComputedRoutesV1Alpha1Type,
Proto: &pbmesh.ComputedRoutes{},
Scope: resource.ScopeNamespace,
Validate: ValidateComputedRoutes,
})
}

View File

@ -32,6 +32,7 @@ func RegisterDestinationPolicy(r resource.Registry) {
r.Register(resource.Registration{
Type: DestinationPolicyV1Alpha1Type,
Proto: &pbmesh.DestinationPolicy{},
Scope: resource.ScopeNamespace,
Validate: ValidateDestinationPolicy,
})
}

View File

@ -32,6 +32,7 @@ func RegisterGRPCRoute(r resource.Registry) {
r.Register(resource.Registration{
Type: GRPCRouteV1Alpha1Type,
Proto: &pbmesh.GRPCRoute{},
Scope: resource.ScopeNamespace,
// TODO(rb): normalize parent/backend ref tenancies in a Mutate hook
Validate: ValidateGRPCRoute,
})

View File

@ -34,6 +34,7 @@ func RegisterHTTPRoute(r resource.Registry) {
r.Register(resource.Registration{
Type: HTTPRouteV1Alpha1Type,
Proto: &pbmesh.HTTPRoute{},
Scope: resource.ScopeNamespace,
Mutate: MutateHTTPRoute,
Validate: ValidateHTTPRoute,
})

View File

@ -12,6 +12,7 @@ import (
"google.golang.org/protobuf/types/known/durationpb"
"github.com/hashicorp/consul/internal/catalog"
"github.com/hashicorp/consul/internal/resource"
"github.com/hashicorp/consul/internal/resource/resourcetest"
pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1"
"github.com/hashicorp/consul/proto-public/pbresource"
@ -962,7 +963,7 @@ func getXRouteRetriesTestCases() map[string]xRouteRetriesTestcase {
}
func newRef(typ *pbresource.Type, name string) *pbresource.Reference {
return resourcetest.Resource(typ, name).Reference("")
return resourcetest.Resource(typ, name).WithTenancy(resource.DefaultNamespacedTenancy()).Reference("")
}
func newBackendRef(typ *pbresource.Type, name, port string) *pbmesh.BackendReference {

View File

@ -27,6 +27,7 @@ func RegisterProxyConfiguration(r resource.Registry) {
r.Register(resource.Registration{
Type: ProxyConfigurationV1Alpha1Type,
Proto: &pbmesh.ProxyConfiguration{},
Scope: resource.ScopeNamespace,
// TODO(rb): add validation for proxy configuration
Validate: nil,
})

View File

@ -28,6 +28,7 @@ func RegisterProxyStateTemplate(r resource.Registry) {
r.Register(resource.Registration{
Type: ProxyStateTemplateV1Alpha1Type,
Proto: &pbmesh.ProxyStateTemplate{},
Scope: resource.ScopeNamespace,
Validate: nil,
ACLs: &resource.ACLHooks{
Read: func(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, id *pbresource.ID) error {

View File

@ -29,6 +29,7 @@ func RegisterTCPRoute(r resource.Registry) {
r.Register(resource.Registration{
Type: TCPRouteV1Alpha1Type,
Proto: &pbmesh.TCPRoute{},
Scope: resource.ScopeNamespace,
// TODO(rb): normalize parent/backend ref tenancies in a Mutate hook
Validate: ValidateTCPRoute,
})

View File

@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/hashicorp/consul/internal/catalog"
"github.com/hashicorp/consul/internal/resource"
"github.com/hashicorp/consul/internal/resource/resourcetest"
pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1"
"github.com/hashicorp/consul/proto/private/prototest"
@ -23,6 +24,7 @@ func TestValidateTCPRoute(t *testing.T) {
run := func(t *testing.T, tc testcase) {
res := resourcetest.Resource(TCPRouteType, "api").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(t, tc.route).
Build()

View File

@ -27,6 +27,7 @@ func RegisterUpstreams(r resource.Registry) {
r.Register(resource.Registration{
Type: UpstreamsV1Alpha1Type,
Proto: &pbmesh.Upstreams{},
Scope: resource.ScopeNamespace,
Validate: nil,
})
}

View File

@ -27,6 +27,7 @@ func RegisterUpstreamsConfiguration(r resource.Registry) {
r.Register(resource.Registration{
Type: UpstreamsConfigurationV1Alpha1Type,
Proto: &pbmesh.UpstreamsConfiguration{},
Scope: resource.ScopeNamespace,
Validate: nil,
})
}

View File

@ -44,6 +44,7 @@ func TestGetDecodedResource(t *testing.T) {
Name: "caspar babypants",
}
res := rtest.Resource(demo.TypeV2Artist, "babypants").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(t, data).
Write(t, client)

View File

@ -128,40 +128,41 @@ func RegisterTypes(r resource.Registry) {
r.Register(resource.Registration{
Type: TypeV1RecordLabel,
Proto: &pbdemov1.RecordLabel{},
Scope: resource.ScopePartition,
ACLs: &resource.ACLHooks{
Read: readACL,
Write: writeACL,
List: makeListACL(TypeV1RecordLabel),
},
Scope: resource.ScopePartition,
})
r.Register(resource.Registration{
Type: TypeV1Artist,
Proto: &pbdemov1.Artist{},
Scope: resource.ScopeNamespace,
ACLs: &resource.ACLHooks{
Read: readACL,
Write: writeACL,
List: makeListACL(TypeV1Artist),
},
Validate: validateV1ArtistFn,
Scope: resource.ScopeNamespace,
})
r.Register(resource.Registration{
Type: TypeV1Album,
Proto: &pbdemov1.Album{},
Scope: resource.ScopeNamespace,
ACLs: &resource.ACLHooks{
Read: readACL,
Write: writeACL,
List: makeListACL(TypeV1Album),
},
Scope: resource.ScopeNamespace,
})
r.Register(resource.Registration{
Type: TypeV2Artist,
Proto: &pbdemov2.Artist{},
Scope: resource.ScopeNamespace,
ACLs: &resource.ACLHooks{
Read: readACL,
Write: writeACL,
@ -169,18 +170,17 @@ func RegisterTypes(r resource.Registry) {
},
Validate: validateV2ArtistFn,
Mutate: mutateV2ArtistFn,
Scope: resource.ScopeNamespace,
})
r.Register(resource.Registration{
Type: TypeV2Album,
Proto: &pbdemov2.Album{},
Scope: resource.ScopeNamespace,
ACLs: &resource.ACLHooks{
Read: readACL,
Write: writeACL,
List: makeListACL(TypeV2Album),
},
Scope: resource.ScopeNamespace,
})
}

View File

@ -47,6 +47,7 @@ func TestResourceHandler_InputValidation(t *testing.T) {
resource.Registration{
Type: demo.TypeV2Artist,
Proto: &pbdemov2.Artist{},
Scope: resource.ScopeNamespace,
},
client,
func(req *http.Request, token *string) { return },

View File

@ -37,25 +37,25 @@ var (
func TestMapper(t *testing.T) {
// Create an advance pointer to some services.
randoSvc := rtest.Resource(fakeBarType, "rando").Build()
apiSvc := rtest.Resource(fakeBarType, "api").Build()
fooSvc := rtest.Resource(fakeBarType, "foo").Build()
barSvc := rtest.Resource(fakeBarType, "bar").Build()
wwwSvc := rtest.Resource(fakeBarType, "www").Build()
randoSvc := rtest.Resource(fakeBarType, "rando").WithTenancy(resource.DefaultNamespacedTenancy()).Build()
apiSvc := rtest.Resource(fakeBarType, "api").WithTenancy(resource.DefaultNamespacedTenancy()).Build()
fooSvc := rtest.Resource(fakeBarType, "foo").WithTenancy(resource.DefaultNamespacedTenancy()).Build()
barSvc := rtest.Resource(fakeBarType, "bar").WithTenancy(resource.DefaultNamespacedTenancy()).Build()
wwwSvc := rtest.Resource(fakeBarType, "www").WithTenancy(resource.DefaultNamespacedTenancy()).Build()
apiRef := newRef(fakeBarType, "api")
fooRef := newRef(fakeBarType, "foo")
barRef := newRef(fakeBarType, "bar")
wwwRef := newRef(fakeBarType, "www")
fail1 := rtest.Resource(fakeFooType, "api").Build()
fail1 := rtest.Resource(fakeFooType, "api").WithTenancy(resource.DefaultNamespacedTenancy()).Build()
fail1Refs := []resource.ReferenceOrID{
apiRef,
fooRef,
barRef,
}
fail2 := rtest.Resource(fakeFooType, "www").Build()
fail2 := rtest.Resource(fakeFooType, "www").WithTenancy(resource.DefaultNamespacedTenancy()).Build()
fail2Refs := []resource.ReferenceOrID{
wwwRef,
fooRef,
@ -352,5 +352,5 @@ func requireLinksForItem(t *testing.T, mapper *Mapper, item *pbresource.ID, link
}
func newRef(typ *pbresource.Type, name string) *pbresource.Reference {
return rtest.Resource(typ, name).Reference("")
return rtest.Resource(typ, name).WithTenancy(resource.DefaultNamespacedTenancy()).Reference("")
}

View File

@ -12,6 +12,7 @@ import (
"google.golang.org/protobuf/proto"
"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/internal/storage"
"github.com/hashicorp/consul/proto-public/pbresource"
)
@ -19,8 +20,17 @@ var (
groupRegexp = regexp.MustCompile(`^[a-z][a-z\d_]+$`)
groupVersionRegexp = regexp.MustCompile(`^v([a-z\d]+)?\d$`)
kindRegexp = regexp.MustCompile(`^[A-Z][A-Za-z\d]+$`)
// Track resource types that are allowed to have an undefined scope. These are usually
// non-customer facing or internal types.
undefinedScopeAllowed = map[string]bool{
storage.UnversionedTypeFrom(TypeV1Tombstone).String(): true,
}
)
func isUndefinedScopeAllowed(t *pbresource.Type) bool {
return undefinedScopeAllowed[storage.UnversionedTypeFrom(t).String()]
}
type Registry interface {
// Register the given resource type and its hooks.
Register(reg Registration)
@ -107,6 +117,14 @@ func (r *TypeRegistry) Register(registration Registration) {
panic(fmt.Sprintf("Type.Kind must be in PascalCase. Got: %q", typ.Kind))
}
if registration.Proto == nil {
panic("Proto field is required.")
}
if registration.Scope == ScopeUndefined && !isUndefinedScopeAllowed(typ) {
panic(fmt.Sprintf("scope required for %s. Got: %q", typ, registration.Scope))
}
r.lock.Lock()
defer r.lock.Unlock()

View File

@ -12,6 +12,8 @@ import (
"github.com/hashicorp/consul/internal/resource/demo"
"github.com/hashicorp/consul/proto-public/pbresource"
pbdemov1 "github.com/hashicorp/consul/proto/private/pbdemo/v1"
demov2 "github.com/hashicorp/consul/proto/private/pbdemo/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
@ -21,7 +23,11 @@ func TestRegister(t *testing.T) {
r := resource.NewRegistry()
// register success
reg := resource.Registration{Type: demo.TypeV2Artist}
reg := resource.Registration{
Type: demo.TypeV2Artist,
Proto: &demov2.Artist{},
Scope: resource.ScopeNamespace,
}
r.Register(reg)
actual, ok := r.Resolve(demo.TypeV2Artist)
require.True(t, ok)
@ -31,11 +37,18 @@ func TestRegister(t *testing.T) {
require.PanicsWithValue(t, "resource type demo.v2.Artist already registered", func() {
r.Register(reg)
})
// register success when scope undefined and type exempt from scope
// skip: can't test this because tombstone type is registered as part of NewRegistry()
}
func TestRegister_Defaults(t *testing.T) {
r := resource.NewRegistry()
r.Register(resource.Registration{Type: demo.TypeV2Artist})
r.Register(resource.Registration{
Type: demo.TypeV2Artist,
Proto: &demov2.Artist{},
Scope: resource.ScopeNamespace,
})
artist, err := demo.GenerateV2Artist()
require.NoError(t, err)
@ -72,21 +85,19 @@ func TestNewRegistry(t *testing.T) {
func TestResolve(t *testing.T) {
r := resource.NewRegistry()
serviceType := &pbresource.Type{
Group: "mesh",
GroupVersion: "v1",
Kind: "Service",
}
// not found
_, ok := r.Resolve(serviceType)
_, ok := r.Resolve(demo.TypeV1Album)
assert.False(t, ok)
// found
r.Register(resource.Registration{Type: serviceType})
registration, ok := r.Resolve(serviceType)
r.Register(resource.Registration{
Type: demo.TypeV1Album,
Proto: &pbdemov1.Album{},
Scope: resource.ScopeNamespace,
})
registration, ok := r.Resolve(demo.TypeV1Album)
assert.True(t, ok)
assert.Equal(t, registration.Type, serviceType)
assert.Equal(t, registration.Type, demo.TypeV1Album)
}
func TestRegister_TypeValidation(t *testing.T) {
@ -163,6 +174,10 @@ func TestRegister_TypeValidation(t *testing.T) {
}
registry.Register(resource.Registration{
Type: typ,
// Just pass anything since proto is a required field.
Proto: &pbdemov1.Artist{},
// Scope is also required
Scope: resource.ScopeNamespace,
})
}

View File

@ -36,11 +36,6 @@ func Resource(rtype *pbresource.Type, name string) *resourceBuilder {
GroupVersion: rtype.GroupVersion,
Kind: rtype.Kind,
},
Tenancy: &pbresource.Tenancy{
Partition: resource.DefaultPartitionName,
Namespace: resource.DefaultNamespaceName,
PeerName: "local",
},
Name: name,
},
},

View File

@ -298,6 +298,10 @@ func UnversionedTypeFrom(t *pbresource.Type) UnversionedType {
}
}
func (u UnversionedType) String() string {
return fmt.Sprintf("%s.%s", u.Group, u.Kind)
}
// GroupVersionMismatchError is returned when a resource is stored as a type
// with a different GroupVersion than was requested.
type GroupVersionMismatchError struct {

View File

@ -236,10 +236,10 @@ type Album struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
YearOfRelease int32 `protobuf:"varint,2,opt,name=year_of_release,json=yearOfRelease,proto3" json:"year_of_release,omitempty"`
CriticallyAclaimed bool `protobuf:"varint,3,opt,name=critically_aclaimed,json=criticallyAclaimed,proto3" json:"critically_aclaimed,omitempty"`
Tracks []string `protobuf:"bytes,4,rep,name=tracks,proto3" json:"tracks,omitempty"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
YearOfRelease int32 `protobuf:"varint,2,opt,name=year_of_release,json=yearOfRelease,proto3" json:"year_of_release,omitempty"`
CriticallyAcclaimed bool `protobuf:"varint,3,opt,name=critically_acclaimed,json=criticallyAcclaimed,proto3" json:"critically_acclaimed,omitempty"`
Tracks []string `protobuf:"bytes,4,rep,name=tracks,proto3" json:"tracks,omitempty"`
}
func (x *Album) Reset() {
@ -288,9 +288,9 @@ func (x *Album) GetYearOfRelease() int32 {
return 0
}
func (x *Album) GetCriticallyAclaimed() bool {
func (x *Album) GetCriticallyAcclaimed() bool {
if x != nil {
return x.CriticallyAclaimed
return x.CriticallyAcclaimed
}
return false
}
@ -323,49 +323,49 @@ var file_private_pbdemo_v1_demo_proto_rawDesc = []byte{
0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x72, 0x65,
0x52, 0x05, 0x67, 0x65, 0x6e, 0x72, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70,
0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c,
0x67, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, 0x8c, 0x01, 0x0a,
0x67, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, 0x8e, 0x01, 0x0a,
0x05, 0x41, 0x6c, 0x62, 0x75, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x79, 0x65,
0x61, 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0d, 0x79, 0x65, 0x61, 0x72, 0x4f, 0x66, 0x52, 0x65, 0x6c, 0x65, 0x61,
0x73, 0x65, 0x12, 0x2f, 0x0a, 0x13, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79,
0x5f, 0x61, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
0x12, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x41, 0x63, 0x6c, 0x61, 0x69,
0x6d, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x04, 0x20,
0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x2a, 0xe9, 0x01, 0x0a, 0x05,
0x47, 0x65, 0x6e, 0x72, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x55,
0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a,
0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x4a, 0x41, 0x5a, 0x5a, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a,
0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x46, 0x4f, 0x4c, 0x4b, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09,
0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x50, 0x4f, 0x50, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x47,
0x45, 0x4e, 0x52, 0x45, 0x5f, 0x4d, 0x45, 0x54, 0x41, 0x4c, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a,
0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x50, 0x55, 0x4e, 0x4b, 0x10, 0x05, 0x12, 0x0f, 0x0a, 0x0b,
0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x42, 0x4c, 0x55, 0x45, 0x53, 0x10, 0x06, 0x12, 0x11, 0x0a,
0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x52, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x42, 0x10, 0x07,
0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x52,
0x59, 0x10, 0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x44, 0x49, 0x53,
0x43, 0x4f, 0x10, 0x09, 0x12, 0x0d, 0x0a, 0x09, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x53, 0x4b,
0x41, 0x10, 0x0a, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x48, 0x49, 0x50,
0x5f, 0x48, 0x4f, 0x50, 0x10, 0x0b, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f,
0x49, 0x4e, 0x44, 0x49, 0x45, 0x10, 0x0c, 0x42, 0x97, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e,
0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x76,
0x31, 0x42, 0x09, 0x44, 0x65, 0x6d, 0x6f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a,
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, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62, 0x64, 0x65, 0x6d, 0x6f,
0x2f, 0x76, 0x31, 0x3b, 0x64, 0x65, 0x6d, 0x6f, 0x76, 0x31, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49,
0x44, 0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f,
0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x44, 0x65,
0x6d, 0x6f, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72,
0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
0x6c, 0x5c, 0x44, 0x65, 0x6d, 0x6f, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68,
0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74,
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x44, 0x65, 0x6d, 0x6f, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50,
0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68,
0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x44, 0x65, 0x6d, 0x6f, 0x3a, 0x3a, 0x56,
0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x73, 0x65, 0x12, 0x31, 0x0a, 0x14, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79,
0x5f, 0x61, 0x63, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
0x52, 0x13, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x41, 0x63, 0x63, 0x6c,
0x61, 0x69, 0x6d, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x18,
0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x2a, 0xe9, 0x01,
0x0a, 0x05, 0x47, 0x65, 0x6e, 0x72, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x47, 0x45, 0x4e, 0x52, 0x45,
0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e,
0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x4a, 0x41, 0x5a, 0x5a, 0x10, 0x01, 0x12, 0x0e,
0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x46, 0x4f, 0x4c, 0x4b, 0x10, 0x02, 0x12, 0x0d,
0x0a, 0x09, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x50, 0x4f, 0x50, 0x10, 0x03, 0x12, 0x0f, 0x0a,
0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x4d, 0x45, 0x54, 0x41, 0x4c, 0x10, 0x04, 0x12, 0x0e,
0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x50, 0x55, 0x4e, 0x4b, 0x10, 0x05, 0x12, 0x0f,
0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x42, 0x4c, 0x55, 0x45, 0x53, 0x10, 0x06, 0x12,
0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x52, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x42,
0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x43, 0x4f, 0x55, 0x4e,
0x54, 0x52, 0x59, 0x10, 0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x44,
0x49, 0x53, 0x43, 0x4f, 0x10, 0x09, 0x12, 0x0d, 0x0a, 0x09, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f,
0x53, 0x4b, 0x41, 0x10, 0x0a, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x48,
0x49, 0x50, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x0b, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52,
0x45, 0x5f, 0x49, 0x4e, 0x44, 0x49, 0x45, 0x10, 0x0c, 0x42, 0x97, 0x02, 0x0a, 0x25, 0x63, 0x6f,
0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73,
0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f,
0x2e, 0x76, 0x31, 0x42, 0x09, 0x44, 0x65, 0x6d, 0x6f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01,
0x5a, 0x3a, 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, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62, 0x64, 0x65,
0x6d, 0x6f, 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x65, 0x6d, 0x6f, 0x76, 0x31, 0xa2, 0x02, 0x04, 0x48,
0x43, 0x49, 0x44, 0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e,
0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e,
0x44, 0x65, 0x6d, 0x6f, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63,
0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72,
0x6e, 0x61, 0x6c, 0x5c, 0x44, 0x65, 0x6d, 0x6f, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x2d, 0x48, 0x61,
0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x44, 0x65, 0x6d, 0x6f, 0x5c, 0x56, 0x31, 0x5c,
0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x25, 0x48, 0x61,
0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a,
0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x44, 0x65, 0x6d, 0x6f, 0x3a,
0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@ -38,6 +38,6 @@ enum Genre {
message Album {
string name = 1;
int32 year_of_release = 2;
bool critically_aclaimed = 3;
bool critically_acclaimed = 3;
repeated string tracks = 4;
}

View File

@ -103,7 +103,7 @@ func (s *ac5_1NoSvcMeshSuite) test(t *testing.T, ct *commonTopo) {
s.testProxyDisabledInDC2(t, cl, peerName)
}
func (s *ac5_1NoSvcMeshSuite) testServiceHealthInCatalog(t *testing.T, ct *commonTopo, cl *api.Client, peer string) {
func (s *ac5_1NoSvcMeshSuite) testServiceHealthInCatalog(t *testing.T, _ *commonTopo, cl *api.Client, peer string) {
t.Run("validate service health in catalog", func(t *testing.T) {
libassert.CatalogServiceExists(t, cl, s.clientSID.Name, &api.QueryOptions{
Peer: peer,

View File

@ -355,7 +355,7 @@ func (s *ac5_2PQFailoverSuite) testPQSingleFailover(t *testing.T, ct *commonTopo
})
}
func (s *ac5_2PQFailoverSuite) testPQZeroFailover(t *testing.T, ct *commonTopo, cl *api.Client, def *api.PreparedQueryDefinition, cluster, peerClu *topology.Cluster, partition string) {
func (s *ac5_2PQFailoverSuite) testPQZeroFailover(t *testing.T, ct *commonTopo, cl *api.Client, def *api.PreparedQueryDefinition, cluster, _ *topology.Cluster, partition string) {
t.Run(fmt.Sprintf("delete failing health check in %s and validate zero failover %s", cluster.Name, cluster.Name), func(t *testing.T) {
cfg := ct.Sprawl.Config()