Skip to content
This repository has been archived by the owner on Jul 11, 2023. It is now read-only.

catalog: add api to fetch service's port:protocol mapping across prov… #2137

Merged
merged 1 commit into from
Dec 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions pkg/catalog/mock_catalog.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions pkg/catalog/service.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package catalog

import (
"reflect"
"strings"

"github.com/pkg/errors"

"github.com/openservicemesh/osm/pkg/service"
)

Expand Down Expand Up @@ -35,3 +38,29 @@ func (mc *MeshCatalog) ListServiceAccountsForService(svc service.MeshService) ([
// Currently OSM uses kubernetes service accounts as service identities
return mc.kubeController.ListServiceAccountsForService(svc)
}

// GetPortToProtocolMappingForService returns a mapping of the service's ports to their corresponding application protocol.
// The function ensures the port:protocol mapping is the same across different endpoint providers for the service, and returns
// an error otherwise.
func (mc *MeshCatalog) GetPortToProtocolMappingForService(svc service.MeshService) (map[uint32]string, error) {
var portToProtocolMap, previous map[uint32]string

for _, provider := range mc.endpointsProviders {
current, err := provider.GetPortToProtocolMappingForService(svc)
if err != nil {
return nil, err
}

if previous != nil && !reflect.DeepEqual(previous, current) {
log.Error().Msgf("Service %s does not have the same port:protocol map across providers: expected=%v, got=%v", svc, previous, current)
return nil, errors.Errorf("Service %s does not have the same port:protocol mapping across providers", svc)
}
previous = current
}
portToProtocolMap = previous
if portToProtocolMap == nil {
return nil, errors.Errorf("Error fetching port:protocol mapping for service %s", svc)
}

return portToProtocolMap, nil
}
99 changes: 99 additions & 0 deletions pkg/catalog/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"

"github.com/openservicemesh/osm/pkg/endpoint"
"github.com/openservicemesh/osm/pkg/kubernetes"
"github.com/openservicemesh/osm/pkg/service"
)
Expand Down Expand Up @@ -54,3 +55,101 @@ func TestListServiceAccountsForService(t *testing.T) {
})
}
}

func TestGetPortToProtocolMappingForService(t *testing.T) {
assert := assert.New(t)
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

type endpointProviderConfig struct {
provider *endpoint.MockProvider
portToProtocolMap map[uint32]string
err error
}

testCases := []struct {
name string
providerConfigs []endpointProviderConfig
expectedPortToProtocolMap map[uint32]string
expectError bool
}{
{
// Test case 1
name: "multiple providers correctly returning the same port:protocol mapping",
providerConfigs: []endpointProviderConfig{
{
// provider 1
provider: endpoint.NewMockProvider(mockCtrl),
portToProtocolMap: map[uint32]string{80: "http", 90: "tcp"},
err: nil,
},
{
// provider 2
provider: endpoint.NewMockProvider(mockCtrl),
portToProtocolMap: map[uint32]string{80: "http", 90: "tcp"},
err: nil,
},
},
expectedPortToProtocolMap: map[uint32]string{80: "http", 90: "tcp"},
expectError: false,
},

{
// Test case 2
name: "multiple providers incorrectly returning different port:protocol mapping",
providerConfigs: []endpointProviderConfig{
{
// provider 1
provider: endpoint.NewMockProvider(mockCtrl),
portToProtocolMap: map[uint32]string{80: "http", 90: "tcp"},
err: nil,
},
{
// provider 2
provider: endpoint.NewMockProvider(mockCtrl),
portToProtocolMap: map[uint32]string{80: "tcp", 90: "http"},
err: nil,
},
},
expectedPortToProtocolMap: nil,
expectError: true,
},

{
// Test case 3
name: "single provider correctly returning port:protocol mapping",
providerConfigs: []endpointProviderConfig{
{
// provider 1
provider: endpoint.NewMockProvider(mockCtrl),
portToProtocolMap: map[uint32]string{80: "http", 90: "tcp"},
err: nil,
},
},
expectedPortToProtocolMap: map[uint32]string{80: "http", 90: "tcp"},
expectError: false,
},
}

testSvc := service.MeshService{Name: "foo", Namespace: "bar"}

for i, tc := range testCases {
t.Run(fmt.Sprintf("Testing test case %d: %s", i, tc.name), func(t *testing.T) {
// Create a list of providers for catalog and mock their calls based on the given config
var allProviders []endpoint.Provider
for _, providerConfig := range tc.providerConfigs {
allProviders = append(allProviders, providerConfig.provider)
providerConfig.provider.EXPECT().GetPortToProtocolMappingForService(testSvc).Return(providerConfig.portToProtocolMap, providerConfig.err).Times(1)
}

mc := &MeshCatalog{
endpointsProviders: allProviders,
}

actualPortToProtocolMap, err := mc.GetPortToProtocolMappingForService(testSvc)

assert.Equal(tc.expectError, err != nil)
assert.Equal(tc.expectedPortToProtocolMap, actualPortToProtocolMap)
})
}
}
3 changes: 3 additions & 0 deletions pkg/catalog/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ type MeshCataloger interface {

// ListMonitoredNamespaces lists namespaces monitored by the control plane
ListMonitoredNamespaces() []string

// GetPortToProtocolMappingForService returns a mapping of the service's ports to their corresponding application protocol
GetPortToProtocolMappingForService(service.MeshService) (map[uint32]string, error)
}

type announcementChannel struct {
Expand Down
123 changes: 123 additions & 0 deletions pkg/endpoint/mock_provider.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.