package appmesh import ( appmesh "github.com/aws/aws-app-mesh-controller-for-k8s/apis/appmesh/v1beta2" "github.com/aws/aws-sdk-go/aws" "github.com/pkg/errors" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "testing" ) func Test_virtualNodeValidator_enforceFieldsImmutability(t *testing.T) { type args struct { vn *appmesh.VirtualNode oldVN *appmesh.VirtualNode } tests := []struct { name string args args wantErr error }{ { name: "VirtualNode immutable fields didn't change", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, }, }, oldVN: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, }, }, }, wantErr: nil, }, { name: "VirtualNode Optional ServiceDiscovery scenario", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, }, }, oldVN: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, }, }, }, wantErr: nil, }, { name: "VirtualNode DNS Servicediscovery change is allowed", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ DNS: &appmesh.DNSServiceDiscovery{Hostname: "dns-new-hostname"}, }, }, }, oldVN: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ DNS: &appmesh.DNSServiceDiscovery{Hostname: "dns-hostname"}, }, }, }, }, wantErr: nil, }, { name: "VirtualNode Servicediscovery mode change from DNS to CloudMap is allowed", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, }, }, oldVN: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ DNS: &appmesh.DNSServiceDiscovery{Hostname: "dns-hostname"}, }, }, }, }, wantErr: nil, }, { name: "VirtualNode field awsName changed", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns_my-cluster"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, }, }, oldVN: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, }, }, }, wantErr: errors.New("VirtualNode update may not change these fields: spec.awsName"), }, { name: "VirtualNode field meshRef changed", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "another-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, }, }, oldVN: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, }, }, }, wantErr: errors.New("VirtualNode update may not change these fields: spec.meshRef"), }, { name: "VirtualNode field awsCloudMap changed", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "new-cloudmap-ns", ServiceName: "new-cloudmap-svc", }, }, }, }, oldVN: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, }, }, }, wantErr: errors.New("VirtualNode update may not change these fields: spec.serviceDiscovery.awsCloudMap"), }, { name: "VirtualNode fields awsName, meshRef and awsCloudMap changed", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns-my-cluster"), MeshRef: &appmesh.MeshReference{ Name: "another-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "new-cloudmap-ns", ServiceName: "new-cloudmap-svc", }, }, }, }, oldVN: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, }, }, }, wantErr: errors.New("VirtualNode update may not change these fields: spec.awsName,spec.meshRef,spec.serviceDiscovery.awsCloudMap"), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { v := &virtualNodeValidator{} err := v.enforceFieldsImmutability(tt.args.vn, tt.args.oldVN) if tt.wantErr != nil { assert.EqualError(t, err, tt.wantErr.Error()) } else { assert.NoError(t, err) } }) } } func Test_virtualNodeValidator_checkVirtualNodeBackendsForDuplicates(t *testing.T) { testARN := "testARN" testPrimaryNamespace := "awesome-ns" testSecondaryNamespace := "secondary-ns" type args struct { vn *appmesh.VirtualNode oldVN *appmesh.VirtualNode } tests := []struct { name string args args wantErr error }{ { name: "Duplicate VirtualService Reference (By Name) included", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, Backends: []appmesh.Backend{ {VirtualService: appmesh.VirtualServiceBackend{ VirtualServiceRef: &appmesh.VirtualServiceReference{ Name: "testVS", Namespace: &testPrimaryNamespace, }, }}, {VirtualService: appmesh.VirtualServiceBackend{ VirtualServiceRef: &appmesh.VirtualServiceReference{ Name: "testVS", Namespace: &testPrimaryNamespace, }, }, }, }, }, }, }, wantErr: errors.New("VirtualNode-my-vn has duplicate VirtualServiceReferences testVS"), }, { name: "Duplicate VirtualService ARN included", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, Backends: []appmesh.Backend{ {VirtualService: appmesh.VirtualServiceBackend{ VirtualServiceARN: &testARN, }, }, {VirtualService: appmesh.VirtualServiceBackend{ VirtualServiceARN: &testARN, }, }, }, }, }, }, wantErr: errors.New("VirtualNode-my-vn has duplicate VirtualServiceReferenceARNs testARN"), }, { name: "No Duplicate Backends", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, Backends: []appmesh.Backend{ {VirtualService: appmesh.VirtualServiceBackend{ VirtualServiceRef: &appmesh.VirtualServiceReference{ Name: "testVS", Namespace: &testPrimaryNamespace, }, }}, }, }, }, }, wantErr: nil, }, { name: "Same VirtualService name across different namespaces", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, Backends: []appmesh.Backend{ {VirtualService: appmesh.VirtualServiceBackend{ VirtualServiceRef: &appmesh.VirtualServiceReference{ Name: "testVS", Namespace: &testPrimaryNamespace, }, }}, {VirtualService: appmesh.VirtualServiceBackend{ VirtualServiceRef: &appmesh.VirtualServiceReference{ Name: "testVS", Namespace: &testSecondaryNamespace, }, }}, }, }, }, }, wantErr: nil, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { v := &virtualNodeValidator{} err := v.checkVirtualNodeBackendsForDuplicates(tt.args.vn) if tt.wantErr != nil { assert.EqualError(t, err, tt.wantErr.Error()) } else { assert.NoError(t, err) } }) } } func Test_virtualNodeValidator_checkRequiredFields(t *testing.T) { testARN := "testARN" type args struct { vn *appmesh.VirtualNode oldVN *appmesh.VirtualNode } tests := []struct { name string args args wantErr error }{ { name: "ServiceDiscovery is Optional if listeners are not specified", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, Backends: []appmesh.Backend{ {VirtualService: appmesh.VirtualServiceBackend{ VirtualServiceARN: &testARN, }, }, }, }, }, }, wantErr: nil, }, { name: "ServiceDiscovery is Mandatory if listeners are specified", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "TestVN", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, Listeners: []appmesh.Listener{ { PortMapping: appmesh.PortMapping{ Port: 8080, Protocol: "http", }, }, }, Backends: []appmesh.Backend{ {VirtualService: appmesh.VirtualServiceBackend{ VirtualServiceARN: &testARN, }, }, }, }, }, }, wantErr: errors.New("ServiceDiscovery missing for VirtualNode-TestVN. ServiceDiscovery must be specified when a listener is specified."), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { v := &virtualNodeValidator{} err := v.checkForRequiredFields(tt.args.vn) if tt.wantErr != nil { assert.EqualError(t, err, tt.wantErr.Error()) } else { assert.NoError(t, err) } }) } } func Test_virtualNodeValidator_checkForConnectionPoolProtocols(t *testing.T) { testPrimaryNamespace := "awesome-ns" type args struct { vn *appmesh.VirtualNode } tests := []struct { name string args args wantErr error }{ { name: "Virtual node listener with one connection pool type", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, Listeners: []appmesh.Listener{ { PortMapping: appmesh.PortMapping{ Port: 8080, Protocol: "http", }, ConnectionPool: &appmesh.VirtualNodeConnectionPool{ HTTP: &appmesh.HTTPConnectionPool{ MaxConnections: 100, MaxPendingRequests: aws.Int64(30), }, }, }, }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, Backends: []appmesh.Backend{ {VirtualService: appmesh.VirtualServiceBackend{ VirtualServiceRef: &appmesh.VirtualServiceReference{ Name: "testVS", Namespace: &testPrimaryNamespace, }, }}, }, }, }, }, wantErr: nil, }, { name: "Virtual node listener with HTTP and TCP connection pools", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, Listeners: []appmesh.Listener{ { PortMapping: appmesh.PortMapping{ Port: 8080, Protocol: "http", }, ConnectionPool: &appmesh.VirtualNodeConnectionPool{ HTTP: &appmesh.HTTPConnectionPool{ MaxConnections: 100, MaxPendingRequests: aws.Int64(30), }, TCP: &appmesh.TCPConnectionPool{ MaxConnections: 100, }, }, }, }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, Backends: []appmesh.Backend{ {VirtualService: appmesh.VirtualServiceBackend{ VirtualServiceRef: &appmesh.VirtualServiceReference{ Name: "testVS", Namespace: &testPrimaryNamespace, }, }}, }, }, }, }, wantErr: errors.New("Only one type of Virtual Node Connection Pool is allowed"), }, { name: "Virtual node listener with HTTP and HTTP2 connection pools", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, Listeners: []appmesh.Listener{ { PortMapping: appmesh.PortMapping{ Port: 8080, Protocol: "http", }, ConnectionPool: &appmesh.VirtualNodeConnectionPool{ HTTP: &appmesh.HTTPConnectionPool{ MaxConnections: 100, MaxPendingRequests: aws.Int64(30), }, HTTP2: &appmesh.HTTP2ConnectionPool{ MaxRequests: 100, }, }, }, }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, Backends: []appmesh.Backend{ {VirtualService: appmesh.VirtualServiceBackend{ VirtualServiceRef: &appmesh.VirtualServiceReference{ Name: "testVS", Namespace: &testPrimaryNamespace, }, }}, }, }, }, }, wantErr: errors.New("Only one type of Virtual Node Connection Pool is allowed"), }, { name: "Virtual node listener with HTTP, HTTP2, TCP, GRPC connection pools", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, Listeners: []appmesh.Listener{ { PortMapping: appmesh.PortMapping{ Port: 8080, Protocol: "http", }, ConnectionPool: &appmesh.VirtualNodeConnectionPool{ HTTP: &appmesh.HTTPConnectionPool{ MaxConnections: 100, MaxPendingRequests: aws.Int64(30), }, HTTP2: &appmesh.HTTP2ConnectionPool{ MaxRequests: 100, }, TCP: &appmesh.TCPConnectionPool{ MaxConnections: 100, }, GRPC: &appmesh.GRPCConnectionPool{ MaxRequests: 100, }, }, }, }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, Backends: []appmesh.Backend{ {VirtualService: appmesh.VirtualServiceBackend{ VirtualServiceRef: &appmesh.VirtualServiceReference{ Name: "testVS", Namespace: &testPrimaryNamespace, }, }}, }, }, }, }, wantErr: errors.New("Only one type of Virtual Node Connection Pool is allowed"), }, { name: "Virtual node listener with no connection pools", args: args{ vn: &appmesh.VirtualNode{ ObjectMeta: metav1.ObjectMeta{ Namespace: "awesome-ns", Name: "my-vn", }, Spec: appmesh.VirtualNodeSpec{ AWSName: aws.String("my-vn_awesome-ns"), MeshRef: &appmesh.MeshReference{ Name: "my-mesh", UID: "408d3036-7dec-11ea-b156-0e30aabe1ca8", }, Listeners: []appmesh.Listener{ { PortMapping: appmesh.PortMapping{ Port: 8080, Protocol: "http", }, }, }, ServiceDiscovery: &appmesh.ServiceDiscovery{ AWSCloudMap: &appmesh.AWSCloudMapServiceDiscovery{ NamespaceName: "cloudmap-ns", ServiceName: "cloudmap-svc", }, }, Backends: []appmesh.Backend{ {VirtualService: appmesh.VirtualServiceBackend{ VirtualServiceRef: &appmesh.VirtualServiceReference{ Name: "testVS", Namespace: &testPrimaryNamespace, }, }}, }, }, }, }, wantErr: nil, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { v := &virtualNodeValidator{} err := v.checkForConnectionPoolProtocols(tt.args.vn) if tt.wantErr != nil { assert.EqualError(t, err, tt.wantErr.Error()) } else { assert.NoError(t, err) } }) } }