Files
tasks/common/rpc/interceptor/namespace_validator_test.go

813 lines
28 KiB
Go

// The MIT License
//
// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package interceptor
import (
"context"
"fmt"
"testing"
"github.com/golang/mock/gomock"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
enumspb "go.temporal.io/api/enums/v1"
"go.temporal.io/api/operatorservice/v1"
"go.temporal.io/api/serviceerror"
"go.temporal.io/api/workflowservice/v1"
"google.golang.org/grpc"
"go.temporal.io/server/api/adminservice/v1"
persistencespb "go.temporal.io/server/api/persistence/v1"
tokenspb "go.temporal.io/server/api/token/v1"
"go.temporal.io/server/common"
"go.temporal.io/server/common/dynamicconfig"
"go.temporal.io/server/common/namespace"
"go.temporal.io/server/common/persistence"
)
type (
namespaceValidatorSuite struct {
suite.Suite
*require.Assertions
controller *gomock.Controller
mockRegistry *namespace.MockRegistry
}
)
func TestNamespaceValidatorSuite(t *testing.T) {
suite.Run(t, &namespaceValidatorSuite{})
}
func (s *namespaceValidatorSuite) SetupSuite() {
}
func (s *namespaceValidatorSuite) TearDownSuite() {
}
func (s *namespaceValidatorSuite) SetupTest() {
s.Assertions = require.New(s.T())
s.controller = gomock.NewController(s.T())
s.mockRegistry = namespace.NewMockRegistry(s.controller)
}
func (s *namespaceValidatorSuite) TearDownTest() {
s.controller.Finish()
}
func (s *namespaceValidatorSuite) Test_StateValidationIntercept_NamespaceNotSet() {
taskToken, _ := common.NewProtoTaskTokenSerializer().Serialize(&tokenspb.Task{
NamespaceId: "",
WorkflowId: "wid",
})
nvi := NewNamespaceValidatorInterceptor(
s.mockRegistry,
dynamicconfig.GetBoolPropertyFn(false),
dynamicconfig.GetIntPropertyFn(100))
serverInfo := &grpc.UnaryServerInfo{
FullMethod: "/temporal/random",
}
testCases := []struct {
expectedErr error
req interface{}
}{
{
req: &workflowservice.StartWorkflowExecutionRequest{},
expectedErr: &serviceerror.InvalidArgument{},
},
{
req: &workflowservice.RespondWorkflowTaskCompletedRequest{
Namespace: "test-namespace", // Ignored, must be set on token.
TaskToken: nil,
},
expectedErr: &serviceerror.InvalidArgument{},
},
{
req: &workflowservice.RespondWorkflowTaskCompletedRequest{
Namespace: "test-namespace", // Ignored, must be set on token.
TaskToken: taskToken,
},
expectedErr: &serviceerror.InvalidArgument{},
},
}
for _, testCase := range testCases {
handlerCalled := false
_, err := nvi.StateValidationIntercept(context.Background(), testCase.req, serverInfo, func(ctx context.Context, req interface{}) (interface{}, error) {
handlerCalled = true
return &workflowservice.StartWorkflowExecutionResponse{}, nil
})
if testCase.expectedErr != nil {
s.IsType(testCase.expectedErr, err)
s.False(handlerCalled)
} else {
s.NoError(err)
s.True(handlerCalled)
}
}
}
func (s *namespaceValidatorSuite) Test_StateValidationIntercept_NamespaceNotFound() {
nvi := NewNamespaceValidatorInterceptor(
s.mockRegistry,
dynamicconfig.GetBoolPropertyFn(false),
dynamicconfig.GetIntPropertyFn(100))
serverInfo := &grpc.UnaryServerInfo{
FullMethod: "/temporal/random",
}
s.mockRegistry.EXPECT().GetNamespace(namespace.Name("not-found-namespace")).Return(nil, serviceerror.NewNamespaceNotFound("missing-namespace"))
req := &workflowservice.StartWorkflowExecutionRequest{Namespace: "not-found-namespace"}
handlerCalled := false
_, err := nvi.StateValidationIntercept(context.Background(), req, serverInfo, func(ctx context.Context, req interface{}) (interface{}, error) {
handlerCalled = true
return &workflowservice.StartWorkflowExecutionResponse{}, nil
})
s.IsType(&serviceerror.NamespaceNotFound{}, err)
s.False(handlerCalled)
s.mockRegistry.EXPECT().GetNamespaceByID(namespace.ID("not-found-namespace-id")).Return(nil, serviceerror.NewNamespaceNotFound("missing-namespace"))
taskToken, _ := common.NewProtoTaskTokenSerializer().Serialize(&tokenspb.Task{
NamespaceId: "not-found-namespace-id",
})
tokenReq := &workflowservice.RespondWorkflowTaskCompletedRequest{
Namespace: "test-namespace",
TaskToken: taskToken,
}
handlerCalled = false
_, err = nvi.StateValidationIntercept(context.Background(), tokenReq, serverInfo, func(ctx context.Context, req interface{}) (interface{}, error) {
handlerCalled = true
return &workflowservice.RespondWorkflowTaskCompletedResponse{}, nil
})
s.IsType(&serviceerror.NamespaceNotFound{}, err)
s.False(handlerCalled)
}
func (s *namespaceValidatorSuite) Test_StateValidationIntercept_StatusFromNamespace() {
testCases := []struct {
state enumspb.NamespaceState
replicationState enumspb.ReplicationState
expectedErr error
method string
req interface{}
}{
// StartWorkflowExecution
{
state: enumspb.NAMESPACE_STATE_REGISTERED,
expectedErr: nil,
method: "/temporal/StartWorkflowExecution",
req: &workflowservice.StartWorkflowExecutionRequest{Namespace: "test-namespace"},
},
{
state: enumspb.NAMESPACE_STATE_DEPRECATED,
expectedErr: &serviceerror.NamespaceInvalidState{},
method: "/temporal/StartWorkflowExecution",
req: &workflowservice.StartWorkflowExecutionRequest{Namespace: "test-namespace"},
},
{
state: enumspb.NAMESPACE_STATE_DELETED,
expectedErr: &serviceerror.NamespaceInvalidState{},
method: "/temporal/StartWorkflowExecution",
req: &workflowservice.StartWorkflowExecutionRequest{Namespace: "test-namespace"},
},
{
state: enumspb.NAMESPACE_STATE_REGISTERED,
replicationState: enumspb.REPLICATION_STATE_HANDOVER,
expectedErr: common.ErrNamespaceHandover,
method: "/temporal/StartWorkflowExecution",
req: &workflowservice.StartWorkflowExecutionRequest{Namespace: "test-namespace"},
},
// DescribeNamespace
{
state: enumspb.NAMESPACE_STATE_UNSPECIFIED,
expectedErr: errNamespaceNotSet,
method: "/temporal/DescribeNamespace",
req: &workflowservice.DescribeNamespaceRequest{},
},
{
state: enumspb.NAMESPACE_STATE_UNSPECIFIED,
expectedErr: nil,
method: "/temporal/DescribeNamespace",
req: &workflowservice.DescribeNamespaceRequest{Id: "test-namespace-id"},
},
{
state: enumspb.NAMESPACE_STATE_UNSPECIFIED,
expectedErr: nil,
method: "/temporal/DescribeNamespace",
req: &workflowservice.DescribeNamespaceRequest{Namespace: "test-namespace"},
},
// RegisterNamespace
{
state: enumspb.NAMESPACE_STATE_UNSPECIFIED,
expectedErr: nil,
method: "/temporal/RegisterNamespace",
req: &workflowservice.RegisterNamespaceRequest{Namespace: "test-namespace"},
},
{
state: enumspb.NAMESPACE_STATE_UNSPECIFIED,
expectedErr: errNamespaceNotSet,
method: "/temporal/RegisterNamespace",
req: &workflowservice.RegisterNamespaceRequest{},
},
// PollWorkflowTaskQueue (default)
{
state: enumspb.NAMESPACE_STATE_REGISTERED,
expectedErr: nil,
method: "/temporal/PollWorkflowTaskQueue",
req: &workflowservice.PollWorkflowTaskQueueRequest{Namespace: "test-namespace"},
},
{
state: enumspb.NAMESPACE_STATE_DEPRECATED,
expectedErr: nil,
method: "/temporal/PollWorkflowTaskQueue",
req: &workflowservice.PollWorkflowTaskQueueRequest{Namespace: "test-namespace"},
},
{
state: enumspb.NAMESPACE_STATE_DELETED,
expectedErr: &serviceerror.NamespaceInvalidState{},
method: "/temporal/PollWorkflowTaskQueue",
req: &workflowservice.PollWorkflowTaskQueueRequest{Namespace: "test-namespace"},
},
// UpdateNamespace
{
state: enumspb.NAMESPACE_STATE_REGISTERED,
expectedErr: nil,
method: "/temporal/UpdateNamespace",
req: &workflowservice.UpdateNamespaceRequest{Namespace: "test-namespace"},
},
{
state: enumspb.NAMESPACE_STATE_DEPRECATED,
expectedErr: nil,
method: "/temporal/UpdateNamespace",
req: &workflowservice.UpdateNamespaceRequest{Namespace: "test-namespace"},
},
{
state: enumspb.NAMESPACE_STATE_REGISTERED,
replicationState: enumspb.REPLICATION_STATE_HANDOVER,
expectedErr: nil,
method: "/temporal/UpdateNamespace",
req: &workflowservice.UpdateNamespaceRequest{Namespace: "test-namespace"},
},
{
state: enumspb.NAMESPACE_STATE_DELETED,
expectedErr: &serviceerror.NamespaceInvalidState{},
method: "/temporal/UpdateNamespace",
req: &workflowservice.UpdateNamespaceRequest{Namespace: "test-namespace"},
},
}
for i, testCase := range testCases {
s.T().Run(fmt.Sprintf("test-case-%v", i), func(t *testing.T) {
_, isDescribeNamespace := testCase.req.(*workflowservice.DescribeNamespaceRequest)
_, isRegisterNamespace := testCase.req.(*workflowservice.RegisterNamespaceRequest)
if !isDescribeNamespace && !isRegisterNamespace {
s.mockRegistry.EXPECT().GetNamespace(namespace.Name("test-namespace")).Return(namespace.FromPersistentState(
&persistence.GetNamespaceResponse{
Namespace: &persistencespb.NamespaceDetail{
Config: &persistencespb.NamespaceConfig{},
ReplicationConfig: &persistencespb.NamespaceReplicationConfig{
State: testCase.replicationState,
},
Info: &persistencespb.NamespaceInfo{
State: testCase.state,
},
},
}), nil)
}
nvi := NewNamespaceValidatorInterceptor(
s.mockRegistry,
dynamicconfig.GetBoolPropertyFn(false),
dynamicconfig.GetIntPropertyFn(100))
serverInfo := &grpc.UnaryServerInfo{
FullMethod: testCase.method,
}
handlerCalled := false
_, err := nvi.StateValidationIntercept(context.Background(), testCase.req, serverInfo, func(ctx context.Context, req interface{}) (interface{}, error) {
handlerCalled = true
return &workflowservice.StartWorkflowExecutionResponse{}, nil
})
if testCase.expectedErr != nil {
s.IsType(testCase.expectedErr, err)
s.False(handlerCalled)
} else {
s.NoError(err)
s.True(handlerCalled)
}
})
}
}
func (s *namespaceValidatorSuite) Test_StateValidationIntercept_StatusFromToken() {
taskToken, _ := common.NewProtoTaskTokenSerializer().Serialize(&tokenspb.Task{
NamespaceId: "test-namespace-id",
})
testCases := []struct {
state enumspb.NamespaceState
expectedErr error
method string
req interface{}
}{
// RespondWorkflowTaskCompleted
{
state: enumspb.NAMESPACE_STATE_REGISTERED,
expectedErr: nil,
method: "/temporal/RespondWorkflowTaskCompleted",
req: &workflowservice.RespondWorkflowTaskCompletedRequest{
TaskToken: taskToken,
},
},
{
state: enumspb.NAMESPACE_STATE_DEPRECATED,
expectedErr: nil,
method: "/temporal/RespondWorkflowTaskCompleted",
req: &workflowservice.RespondWorkflowTaskCompletedRequest{
TaskToken: taskToken,
},
},
{
state: enumspb.NAMESPACE_STATE_DELETED,
expectedErr: &serviceerror.NamespaceInvalidState{},
method: "/temporal/RespondWorkflowTaskCompleted",
req: &workflowservice.RespondWorkflowTaskCompletedRequest{
TaskToken: taskToken,
},
},
}
for _, testCase := range testCases {
s.mockRegistry.EXPECT().GetNamespaceByID(namespace.ID("test-namespace-id")).Return(namespace.FromPersistentState(
&persistence.GetNamespaceResponse{
Namespace: &persistencespb.NamespaceDetail{
Config: &persistencespb.NamespaceConfig{},
ReplicationConfig: &persistencespb.NamespaceReplicationConfig{},
Info: &persistencespb.NamespaceInfo{
State: testCase.state,
},
},
}), nil)
nvi := NewNamespaceValidatorInterceptor(
s.mockRegistry,
dynamicconfig.GetBoolPropertyFn(false),
dynamicconfig.GetIntPropertyFn(100))
serverInfo := &grpc.UnaryServerInfo{
FullMethod: testCase.method,
}
handlerCalled := false
_, err := nvi.StateValidationIntercept(context.Background(), testCase.req, serverInfo, func(ctx context.Context, req interface{}) (interface{}, error) {
handlerCalled = true
return &workflowservice.RespondWorkflowTaskCompletedResponse{}, nil
})
if testCase.expectedErr != nil {
s.IsType(testCase.expectedErr, err)
s.False(handlerCalled)
} else {
s.NoError(err)
s.True(handlerCalled)
}
}
}
func (s *namespaceValidatorSuite) Test_StateValidationIntercept_DescribeNamespace_Id() {
nvi := NewNamespaceValidatorInterceptor(
s.mockRegistry,
dynamicconfig.GetBoolPropertyFn(false),
dynamicconfig.GetIntPropertyFn(100))
serverInfo := &grpc.UnaryServerInfo{
FullMethod: "/temporal/random",
}
req := &workflowservice.DescribeNamespaceRequest{Id: "test-namespace-id"}
handlerCalled := false
_, err := nvi.StateValidationIntercept(context.Background(), req, serverInfo, func(ctx context.Context, req interface{}) (interface{}, error) {
handlerCalled = true
return &workflowservice.DescribeNamespaceResponse{}, nil
})
s.NoError(err)
s.True(handlerCalled)
req = &workflowservice.DescribeNamespaceRequest{}
handlerCalled = false
_, err = nvi.StateValidationIntercept(context.Background(), req, serverInfo, func(ctx context.Context, req interface{}) (interface{}, error) {
handlerCalled = true
return &workflowservice.DescribeNamespaceResponse{}, nil
})
s.IsType(&serviceerror.InvalidArgument{}, err)
s.False(handlerCalled)
}
func (s *namespaceValidatorSuite) Test_StateValidationIntercept_GetClusterInfo() {
nvi := NewNamespaceValidatorInterceptor(
s.mockRegistry,
dynamicconfig.GetBoolPropertyFn(false),
dynamicconfig.GetIntPropertyFn(100))
serverInfo := &grpc.UnaryServerInfo{
FullMethod: "/temporal/random",
}
// Example of API which doesn't have namespace field.
req := &workflowservice.GetClusterInfoRequest{}
handlerCalled := false
_, err := nvi.StateValidationIntercept(context.Background(), req, serverInfo, func(ctx context.Context, req interface{}) (interface{}, error) {
handlerCalled = true
return &workflowservice.GetClusterInfoResponse{}, nil
})
s.NoError(err)
s.True(handlerCalled)
}
func (s *namespaceValidatorSuite) Test_Intercept_RegisterNamespace() {
nvi := NewNamespaceValidatorInterceptor(
s.mockRegistry,
dynamicconfig.GetBoolPropertyFn(false),
dynamicconfig.GetIntPropertyFn(100))
serverInfo := &grpc.UnaryServerInfo{
FullMethod: "/temporal/random",
}
req := &workflowservice.RegisterNamespaceRequest{Namespace: "new-namespace"}
handlerCalled := false
_, err := nvi.StateValidationIntercept(context.Background(), req, serverInfo, func(ctx context.Context, req interface{}) (interface{}, error) {
handlerCalled = true
return &workflowservice.RegisterNamespaceResponse{}, nil
})
s.NoError(err)
s.True(handlerCalled)
req = &workflowservice.RegisterNamespaceRequest{}
handlerCalled = false
_, err = nvi.StateValidationIntercept(context.Background(), req, serverInfo, func(ctx context.Context, req interface{}) (interface{}, error) {
handlerCalled = true
return &workflowservice.RegisterNamespaceResponse{}, nil
})
s.IsType(&serviceerror.InvalidArgument{}, err)
s.False(handlerCalled)
}
func (s *namespaceValidatorSuite) Test_StateValidationIntercept_TokenNamespaceEnforcement() {
testCases := []struct {
tokenNamespaceID namespace.ID
tokenNamespaceName namespace.Name
requestNamespaceID namespace.ID
requestNamespaceName namespace.Name
enableTokenNamespaceEnforcement bool
expectedErr error
}{
{
tokenNamespaceID: "valid-id",
tokenNamespaceName: "valid-name",
requestNamespaceID: "valid-id",
requestNamespaceName: "valid-name",
enableTokenNamespaceEnforcement: true,
expectedErr: nil,
},
{
tokenNamespaceID: "valid-id",
tokenNamespaceName: "valid-name",
requestNamespaceID: "valid-id",
requestNamespaceName: "valid-name",
enableTokenNamespaceEnforcement: false,
expectedErr: nil,
},
{
tokenNamespaceID: "valid-id",
tokenNamespaceName: "valid-name",
requestNamespaceID: "invalid-id",
requestNamespaceName: "invalid-name",
enableTokenNamespaceEnforcement: true,
expectedErr: &serviceerror.InvalidArgument{},
},
{
tokenNamespaceID: "valid-id",
tokenNamespaceName: "valid-name",
requestNamespaceID: "invalid-id",
requestNamespaceName: "invalid-name",
enableTokenNamespaceEnforcement: false,
expectedErr: nil,
},
}
for _, testCase := range testCases {
taskToken, _ := common.NewProtoTaskTokenSerializer().Serialize(&tokenspb.Task{
NamespaceId: testCase.tokenNamespaceID.String(),
})
tokenNamespace := namespace.FromPersistentState(
&persistence.GetNamespaceResponse{
Namespace: &persistencespb.NamespaceDetail{
Config: &persistencespb.NamespaceConfig{},
ReplicationConfig: &persistencespb.NamespaceReplicationConfig{},
Info: &persistencespb.NamespaceInfo{
Id: testCase.tokenNamespaceID.String(),
Name: testCase.tokenNamespaceName.String(),
State: enumspb.NAMESPACE_STATE_REGISTERED,
},
},
})
req := &workflowservice.RespondWorkflowTaskCompletedRequest{
Namespace: testCase.requestNamespaceName.String(),
TaskToken: taskToken,
}
queryReq := &workflowservice.RespondQueryTaskCompletedRequest{
Namespace: testCase.requestNamespaceName.String(),
TaskToken: taskToken,
}
requestNamespace := namespace.FromPersistentState(
&persistence.GetNamespaceResponse{
Namespace: &persistencespb.NamespaceDetail{
Config: &persistencespb.NamespaceConfig{},
ReplicationConfig: &persistencespb.NamespaceReplicationConfig{},
Info: &persistencespb.NamespaceInfo{
Id: testCase.requestNamespaceID.String(),
Name: testCase.requestNamespaceName.String(),
State: enumspb.NAMESPACE_STATE_REGISTERED,
},
},
})
// 2 times because of RespondQueryTaskCompleted.
s.mockRegistry.EXPECT().GetNamespace(testCase.requestNamespaceName).Return(requestNamespace, nil).Times(2)
s.mockRegistry.EXPECT().GetNamespaceByID(testCase.tokenNamespaceID).Return(tokenNamespace, nil).Times(2)
nvi := NewNamespaceValidatorInterceptor(
s.mockRegistry,
dynamicconfig.GetBoolPropertyFn(testCase.enableTokenNamespaceEnforcement),
dynamicconfig.GetIntPropertyFn(100))
serverInfo := &grpc.UnaryServerInfo{
FullMethod: "/temporal/RandomMethod",
}
handlerCalled := false
_, err := nvi.StateValidationIntercept(context.Background(), req, serverInfo, func(ctx context.Context, req interface{}) (interface{}, error) {
handlerCalled = true
return &workflowservice.RespondWorkflowTaskCompletedResponse{}, nil
})
_, queryErr := nvi.StateValidationIntercept(context.Background(), queryReq, serverInfo, func(ctx context.Context, req interface{}) (interface{}, error) {
handlerCalled = true
return &workflowservice.RespondQueryTaskCompletedResponse{}, nil
})
if testCase.expectedErr != nil {
s.IsType(testCase.expectedErr, err)
s.IsType(testCase.expectedErr, queryErr)
s.False(handlerCalled)
} else {
s.NoError(err)
s.NoError(queryErr)
s.True(handlerCalled)
}
}
}
func (s *namespaceValidatorSuite) Test_Intercept_SearchAttributeRequests() {
// it's just a list of requests
testCases := []struct {
req any
hasNamespace bool
}{
{
req: &adminservice.AddSearchAttributesRequest{},
hasNamespace: false,
},
{
req: &adminservice.RemoveSearchAttributesRequest{},
hasNamespace: false,
},
{
req: &adminservice.GetSearchAttributesRequest{},
hasNamespace: false,
},
{
req: &operatorservice.AddSearchAttributesRequest{},
hasNamespace: false,
},
{
req: &operatorservice.RemoveSearchAttributesRequest{},
hasNamespace: false,
},
{
req: &operatorservice.ListSearchAttributesRequest{},
hasNamespace: false,
},
{
req: &adminservice.AddSearchAttributesRequest{Namespace: "test-namespace"},
hasNamespace: true,
},
{
req: &adminservice.RemoveSearchAttributesRequest{Namespace: "test-namespace"},
hasNamespace: true,
},
{
req: &adminservice.GetSearchAttributesRequest{Namespace: "test-namespace"},
hasNamespace: true,
},
{
req: &operatorservice.AddSearchAttributesRequest{Namespace: "test-namespace"},
hasNamespace: true,
},
{
req: &operatorservice.RemoveSearchAttributesRequest{Namespace: "test-namespace"},
hasNamespace: true,
},
{
req: &operatorservice.ListSearchAttributesRequest{Namespace: "test-namespace"},
hasNamespace: true,
},
}
for _, testCase := range testCases {
if testCase.hasNamespace {
s.mockRegistry.EXPECT().GetNamespace(namespace.Name("test-namespace")).Return(nil, nil)
}
nvi := NewNamespaceValidatorInterceptor(
s.mockRegistry,
dynamicconfig.GetBoolPropertyFn(false),
dynamicconfig.GetIntPropertyFn(100),
)
serverInfo := &grpc.UnaryServerInfo{
FullMethod: "/temporal/random",
}
handlerCalled := false
_, err := nvi.StateValidationIntercept(
context.Background(),
testCase.req,
serverInfo,
func(ctx context.Context, req any) (any, error) {
handlerCalled = true
return nil, nil
},
)
s.NoError(err)
s.True(handlerCalled)
}
}
func (s *namespaceValidatorSuite) Test_NamespaceValidateIntercept() {
nvi := NewNamespaceValidatorInterceptor(
s.mockRegistry,
dynamicconfig.GetBoolPropertyFn(false),
dynamicconfig.GetIntPropertyFn(10))
serverInfo := &grpc.UnaryServerInfo{
FullMethod: "/temporal/random",
}
requestNamespace := namespace.FromPersistentState(
&persistence.GetNamespaceResponse{
Namespace: &persistencespb.NamespaceDetail{
Config: &persistencespb.NamespaceConfig{},
ReplicationConfig: &persistencespb.NamespaceReplicationConfig{},
Info: &persistencespb.NamespaceInfo{
Id: uuid.New().String(),
Name: "namespace",
State: enumspb.NAMESPACE_STATE_REGISTERED,
},
},
})
requestNamespaceTooLong := namespace.FromPersistentState(
&persistence.GetNamespaceResponse{
Namespace: &persistencespb.NamespaceDetail{
Config: &persistencespb.NamespaceConfig{},
ReplicationConfig: &persistencespb.NamespaceReplicationConfig{},
Info: &persistencespb.NamespaceInfo{
Id: uuid.New().String(),
Name: "namespaceTooLong",
State: enumspb.NAMESPACE_STATE_REGISTERED,
},
},
})
s.mockRegistry.EXPECT().GetNamespace(namespace.Name("namespace")).Return(requestNamespace, nil).AnyTimes()
s.mockRegistry.EXPECT().GetNamespace(namespace.Name("namespaceTooLong")).Return(requestNamespaceTooLong, nil).AnyTimes()
req := &workflowservice.StartWorkflowExecutionRequest{Namespace: "namespace"}
handlerCalled := false
_, err := nvi.NamespaceValidateIntercept(context.Background(), req, serverInfo, func(ctx context.Context, req interface{}) (interface{}, error) {
handlerCalled = true
return &workflowservice.StartWorkflowExecutionResponse{}, nil
})
s.True(handlerCalled)
s.NoError(err)
req = &workflowservice.StartWorkflowExecutionRequest{Namespace: "namespaceTooLong"}
handlerCalled = false
_, err = nvi.NamespaceValidateIntercept(context.Background(), req, serverInfo, func(ctx context.Context, req interface{}) (interface{}, error) {
handlerCalled = true
return &workflowservice.StartWorkflowExecutionResponse{}, nil
})
s.False(handlerCalled)
s.Error(err)
}
func (s *namespaceValidatorSuite) TestSetNamespace() {
namespaceRequestName := uuid.New().String()
namespaceEntryName := uuid.New().String()
namespaceEntry := namespace.FromPersistentState(
&persistence.GetNamespaceResponse{
Namespace: &persistencespb.NamespaceDetail{
Config: &persistencespb.NamespaceConfig{},
ReplicationConfig: &persistencespb.NamespaceReplicationConfig{},
Info: &persistencespb.NamespaceInfo{
Id: uuid.New().String(),
Name: namespaceEntryName,
State: enumspb.NAMESPACE_STATE_REGISTERED,
},
},
})
nvi := NewNamespaceValidatorInterceptor(
s.mockRegistry,
dynamicconfig.GetBoolPropertyFn(false),
dynamicconfig.GetIntPropertyFn(10),
)
queryReq := &workflowservice.RespondQueryTaskCompletedRequest{}
nvi.setNamespace(namespaceEntry, queryReq)
s.Equal(namespaceEntryName, queryReq.Namespace)
queryReq.Namespace = namespaceRequestName
nvi.setNamespace(namespaceEntry, queryReq)
s.Equal(namespaceRequestName, queryReq.Namespace)
completeWorkflowTaskReq := &workflowservice.RespondWorkflowTaskCompletedRequest{}
nvi.setNamespace(namespaceEntry, completeWorkflowTaskReq)
s.Equal(namespaceEntryName, completeWorkflowTaskReq.Namespace)
completeWorkflowTaskReq.Namespace = namespaceRequestName
nvi.setNamespace(namespaceEntry, completeWorkflowTaskReq)
s.Equal(namespaceRequestName, completeWorkflowTaskReq.Namespace)
failWorkflowTaskReq := &workflowservice.RespondWorkflowTaskFailedRequest{}
nvi.setNamespace(namespaceEntry, failWorkflowTaskReq)
s.Equal(namespaceEntryName, failWorkflowTaskReq.Namespace)
failWorkflowTaskReq.Namespace = namespaceRequestName
nvi.setNamespace(namespaceEntry, failWorkflowTaskReq)
s.Equal(namespaceRequestName, failWorkflowTaskReq.Namespace)
heartbeatActivityTaskReq := &workflowservice.RecordActivityTaskHeartbeatRequest{}
nvi.setNamespace(namespaceEntry, heartbeatActivityTaskReq)
s.Equal(namespaceEntryName, heartbeatActivityTaskReq.Namespace)
heartbeatActivityTaskReq.Namespace = namespaceRequestName
nvi.setNamespace(namespaceEntry, heartbeatActivityTaskReq)
s.Equal(namespaceRequestName, heartbeatActivityTaskReq.Namespace)
cancelActivityTaskReq := &workflowservice.RespondActivityTaskCanceledRequest{}
nvi.setNamespace(namespaceEntry, cancelActivityTaskReq)
s.Equal(namespaceEntryName, cancelActivityTaskReq.Namespace)
cancelActivityTaskReq.Namespace = namespaceRequestName
nvi.setNamespace(namespaceEntry, cancelActivityTaskReq)
s.Equal(namespaceRequestName, cancelActivityTaskReq.Namespace)
completeActivityTaskReq := &workflowservice.RespondActivityTaskCompletedRequest{}
nvi.setNamespace(namespaceEntry, completeActivityTaskReq)
s.Equal(namespaceEntryName, completeActivityTaskReq.Namespace)
completeActivityTaskReq.Namespace = namespaceRequestName
nvi.setNamespace(namespaceEntry, completeActivityTaskReq)
s.Equal(namespaceRequestName, completeActivityTaskReq.Namespace)
failActivityTaskReq := &workflowservice.RespondActivityTaskFailedRequest{}
nvi.setNamespace(namespaceEntry, failActivityTaskReq)
s.Equal(namespaceEntryName, failActivityTaskReq.Namespace)
failActivityTaskReq.Namespace = namespaceRequestName
nvi.setNamespace(namespaceEntry, failActivityTaskReq)
s.Equal(namespaceRequestName, failActivityTaskReq.Namespace)
}