mirror of
https://github.com/googleforgames/open-match.git
synced 2025-03-25 13:24:18 +00:00
Moved MMF for end-to-end in-cluster testing to internal (#1014)
* Moved MMF for end-to-end in-cluster testing to internal * Fix
This commit is contained in:
2
Makefile
2
Makefile
@ -244,7 +244,7 @@ build-mmf-go-rosterbased-image: docker build-base-build-image
|
||||
docker build -f examples/functions/golang/rosterbased/Dockerfile -t $(REGISTRY)/openmatch-mmf-go-rosterbased:$(TAG) -t $(REGISTRY)/openmatch-mmf-go-rosterbased:$(ALTERNATE_TAG) .
|
||||
|
||||
build-mmf-go-pool-image: docker build-base-build-image
|
||||
docker build -f examples/functions/golang/pool/Dockerfile -t $(REGISTRY)/openmatch-mmf-go-pool:$(TAG) -t $(REGISTRY)/openmatch-mmf-go-pool:$(ALTERNATE_TAG) .
|
||||
docker build -f test/customize/matchfunction/Dockerfile -t $(REGISTRY)/openmatch-mmf-go-pool:$(TAG) -t $(REGISTRY)/openmatch-mmf-go-pool:$(ALTERNATE_TAG) .
|
||||
|
||||
build-evaluator-go-simple-image: docker build-base-build-image
|
||||
docker build -f test/evaluator/Dockerfile -t $(REGISTRY)/openmatch-evaluator-go-simple:$(TAG) -t $(REGISTRY)/openmatch-evaluator-go-simple:$(ALTERNATE_TAG) .
|
||||
|
@ -21,16 +21,17 @@ import (
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/assert"
|
||||
pool "open-match.dev/open-match/examples/functions/golang/pool/mmf"
|
||||
"open-match.dev/open-match/internal/app/minimatch"
|
||||
"open-match.dev/open-match/internal/rpc"
|
||||
rpcTesting "open-match.dev/open-match/internal/rpc/testing"
|
||||
statestoreTesting "open-match.dev/open-match/internal/statestore/testing"
|
||||
"open-match.dev/open-match/internal/telemetry"
|
||||
"open-match.dev/open-match/internal/testing/customize/evaluator"
|
||||
internalMmf "open-match.dev/open-match/internal/testing/mmf"
|
||||
"open-match.dev/open-match/internal/util"
|
||||
mmfHarness "open-match.dev/open-match/pkg/harness/function/golang"
|
||||
pb "open-match.dev/open-match/pkg/pb"
|
||||
"open-match.dev/open-match/test/customize/matchfunction/mmf"
|
||||
|
||||
"open-match.dev/open-match/test/evaluator/evaluate"
|
||||
)
|
||||
|
||||
@ -162,8 +163,8 @@ func createMatchFunctionForTest(t *testing.T, c *rpcTesting.TestContext) *rpcTes
|
||||
cfg.Set("api.mmlogic.grpcport", c.GetGRPCPort())
|
||||
cfg.Set("api.mmlogic.httpport", c.GetHTTPPort())
|
||||
|
||||
assert.Nil(t, mmfHarness.BindService(p, cfg, &mmfHarness.FunctionSettings{
|
||||
Func: pool.MakeMatches,
|
||||
assert.Nil(t, internalMmf.BindService(p, cfg, &internalMmf.FunctionSettings{
|
||||
Func: mmf.MakeMatches,
|
||||
}))
|
||||
})
|
||||
return tc
|
||||
|
64
internal/testing/mmf/matchfunction.go
Normal file
64
internal/testing/mmf/matchfunction.go
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright 2019 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package mmf provides the Match Making Function service for Open Match golang harness.
|
||||
package mmf
|
||||
|
||||
import (
|
||||
"github.com/spf13/viper"
|
||||
"google.golang.org/grpc"
|
||||
"open-match.dev/open-match/internal/app"
|
||||
"open-match.dev/open-match/internal/config"
|
||||
"open-match.dev/open-match/internal/rpc"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
)
|
||||
|
||||
// FunctionSettings is a collection of parameters used to customize matchfunction views.
|
||||
type FunctionSettings struct {
|
||||
Func MatchFunction
|
||||
}
|
||||
|
||||
// RunMatchFunction is a hook for the main() method in the main executable.
|
||||
func RunMatchFunction(settings *FunctionSettings) {
|
||||
app.RunApplication("functions", getCfg, func(p *rpc.ServerParams, cfg config.View) error {
|
||||
return BindService(p, cfg, settings)
|
||||
})
|
||||
}
|
||||
|
||||
// BindService creates the function service to the server Params.
|
||||
func BindService(p *rpc.ServerParams, cfg config.View, fs *FunctionSettings) error {
|
||||
service, err := newMatchFunctionService(cfg, fs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.AddHandleFunc(func(s *grpc.Server) {
|
||||
pb.RegisterMatchFunctionServer(s, service)
|
||||
}, pb.RegisterMatchFunctionHandlerFromEndpoint)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getCfg() (config.View, error) {
|
||||
cfg := viper.New()
|
||||
|
||||
cfg.Set("api.functions.hostname", "om-function")
|
||||
cfg.Set("api.functions.grpcport", 50502)
|
||||
cfg.Set("api.functions.httpport", 51502)
|
||||
|
||||
cfg.Set("api.mmlogic.hostname", "om-mmlogic")
|
||||
cfg.Set("api.mmlogic.grpcport", 50503)
|
||||
|
||||
return cfg, nil
|
||||
}
|
153
internal/testing/mmf/matchfunction_service.go
Normal file
153
internal/testing/mmf/matchfunction_service.go
Normal file
@ -0,0 +1,153 @@
|
||||
// Copyright 2019 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package mmf provides the Match Making Function service for Open Match golang harness.
|
||||
package mmf
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/any"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
"open-match.dev/open-match/internal/config"
|
||||
"open-match.dev/open-match/internal/rpc"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
)
|
||||
|
||||
var (
|
||||
logger = logrus.WithFields(logrus.Fields{
|
||||
"app": "openmatch",
|
||||
"component": "matchfunction.harness.golang",
|
||||
})
|
||||
)
|
||||
|
||||
// MatchFunction is the function signature for the Match Making Function (MMF) to be implemented by the user.
|
||||
// The harness will pass the Rosters and PlayerPool for the match profile to this
|
||||
// function and it will return the Rosters to be populated in the proposal.
|
||||
// Input:
|
||||
// - MatchFunctionParams:
|
||||
// A structure that defines the resources that are available to the match function.
|
||||
// Developers can choose to add context to the structure such that match function has the ability
|
||||
// to cancel a stream response/request or to limit match function by sharing a static and protected view.
|
||||
type MatchFunction func(*MatchFunctionParams) ([]*pb.Match, error)
|
||||
|
||||
// matchFunctionService implements pb.MatchFunctionServer, the server generated
|
||||
// by compiling the protobuf, by fulfilling the pb.MatchFunctionServer interface.
|
||||
type matchFunctionService struct {
|
||||
cfg config.View
|
||||
function MatchFunction
|
||||
mmlogicClient pb.MmLogicClient
|
||||
}
|
||||
|
||||
// MatchFunctionParams is a protected view for the match function.
|
||||
type MatchFunctionParams struct {
|
||||
// Logger is used to generate error/debug logs
|
||||
Logger *logrus.Entry
|
||||
|
||||
// 'Name' from the MatchProfile.
|
||||
ProfileName string
|
||||
|
||||
// 'Extensions' from the MatchProfile.
|
||||
Extensions map[string]*any.Any
|
||||
|
||||
// An array of Rosters. By convention, your input Roster contains players already in
|
||||
// the match, and the names of pools to search when trying to fill an empty slot.
|
||||
Rosters []*pb.Roster
|
||||
|
||||
// A map that contains mappings from pool name to a list of tickets that satisfied the filters in the pool
|
||||
PoolNameToTickets map[string][]*pb.Ticket
|
||||
}
|
||||
|
||||
// Run is this harness's implementation of the gRPC call defined in api/matchfunction.proto.
|
||||
func (s *matchFunctionService) Run(req *pb.RunRequest, stream pb.MatchFunction_RunServer) error {
|
||||
poolNameToTickets, err := s.getMatchManifest(stream.Context(), req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// The matchfunction takes in some half-filled/empty rosters, a property bag, and a map[poolNames]tickets to generate match proposals
|
||||
mfParams := &MatchFunctionParams{
|
||||
Logger: logrus.WithFields(logrus.Fields{
|
||||
"app": "openmatch",
|
||||
"component": "matchfunction.implementation",
|
||||
}),
|
||||
ProfileName: req.GetProfile().GetName(),
|
||||
Extensions: req.GetProfile().GetExtensions(),
|
||||
Rosters: req.GetProfile().GetRosters(),
|
||||
PoolNameToTickets: poolNameToTickets,
|
||||
}
|
||||
// Run the customize match function!
|
||||
proposals, err := s.function(mfParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logger.WithFields(logrus.Fields{
|
||||
"proposals": proposals,
|
||||
}).Trace("proposals returned by match function")
|
||||
|
||||
for _, proposal := range proposals {
|
||||
if err := stream.Send(&pb.RunResponse{Proposal: proposal}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func newMatchFunctionService(cfg config.View, fs *FunctionSettings) (*matchFunctionService, error) {
|
||||
conn, err := rpc.GRPCClientFromConfig(cfg, "api.mmlogic")
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to get MMLogic connection, %v.", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mmfService := &matchFunctionService{cfg: cfg, function: fs.Func, mmlogicClient: pb.NewMmLogicClient(conn)}
|
||||
return mmfService, nil
|
||||
}
|
||||
|
||||
// getMatchManifest fetches all the data needed from the mmlogic API.
|
||||
func (s *matchFunctionService) getMatchManifest(ctx context.Context, req *pb.RunRequest) (map[string][]*pb.Ticket, error) {
|
||||
poolNameToTickets := make(map[string][]*pb.Ticket)
|
||||
filterPools := req.GetProfile().GetPools()
|
||||
|
||||
for _, pool := range filterPools {
|
||||
qtClient, err := s.mmlogicClient.QueryTickets(ctx, &pb.QueryTicketsRequest{Pool: pool}, grpc.WaitForReady(true))
|
||||
if err != nil {
|
||||
logger.WithError(err).Error("Failed to get queryTicketClient from mmlogic.")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Aggregate tickets by poolName
|
||||
poolTickets := make([]*pb.Ticket, 0)
|
||||
for {
|
||||
qtResponse, err := qtClient.Recv()
|
||||
if err == io.EOF {
|
||||
logger.Trace("Received all results from the queryTicketClient.")
|
||||
// Break when all results are received
|
||||
break
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logger.WithError(err).Error("Failed to receive a response from the queryTicketClient.")
|
||||
return nil, err
|
||||
}
|
||||
poolTickets = append(poolTickets, qtResponse.Tickets...)
|
||||
}
|
||||
poolNameToTickets[pool.GetName()] = poolTickets
|
||||
}
|
||||
|
||||
return poolNameToTickets, nil
|
||||
}
|
@ -14,11 +14,11 @@
|
||||
|
||||
FROM open-match-base-build as builder
|
||||
|
||||
WORKDIR /go/src/open-match.dev/open-match/examples/functions/golang/pool
|
||||
WORKDIR /go/src/open-match.dev/open-match/test/customize/matchfunction
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o matchfunction .
|
||||
|
||||
FROM gcr.io/distroless/static:nonroot
|
||||
WORKDIR /app/
|
||||
COPY --from=builder --chown=nonroot /go/src/open-match.dev/open-match/examples/functions/golang/pool/matchfunction /app/
|
||||
COPY --from=builder --chown=nonroot /go/src/open-match.dev/open-match/test/customize/matchfunction/matchfunction /app/
|
||||
|
||||
ENTRYPOINT ["/app/matchfunction"]
|
@ -20,8 +20,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
pool "open-match.dev/open-match/examples/functions/golang/pool/mmf"
|
||||
mmfHarness "open-match.dev/open-match/pkg/harness/function/golang"
|
||||
internalMmf "open-match.dev/open-match/internal/testing/mmf"
|
||||
"open-match.dev/open-match/test/customize/matchfunction/mmf"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -29,7 +29,7 @@ func main() {
|
||||
// match function. The harness itself queries open match for player pools for
|
||||
// the specified request and passes the pools to the match function to generate
|
||||
// proposals.
|
||||
mmfHarness.RunMatchFunction(&mmfHarness.FunctionSettings{
|
||||
Func: pool.MakeMatches,
|
||||
internalMmf.RunMatchFunction(&internalMmf.FunctionSettings{
|
||||
Func: mmf.MakeMatches,
|
||||
})
|
||||
}
|
@ -24,7 +24,7 @@ import (
|
||||
"github.com/golang/protobuf/ptypes/any"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/xid"
|
||||
mmfHarness "open-match.dev/open-match/pkg/harness/function/golang"
|
||||
internalMmf "open-match.dev/open-match/internal/testing/mmf"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
)
|
||||
|
||||
@ -37,7 +37,7 @@ var (
|
||||
// The goal of this function is to generate predictable matches that can be validated without flakyness.
|
||||
// This match function loops through all the pools and generates one match per pool aggregating all players
|
||||
// in that pool in the generated match.
|
||||
func MakeMatches(params *mmfHarness.MatchFunctionParams) ([]*pb.Match, error) {
|
||||
func MakeMatches(params *internalMmf.MatchFunctionParams) ([]*pb.Match, error) {
|
||||
var result []*pb.Match
|
||||
for pool, tickets := range params.PoolNameToTickets {
|
||||
if len(tickets) != 0 {
|
@ -23,7 +23,7 @@ import (
|
||||
"github.com/golang/protobuf/ptypes/any"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
mmfHarness "open-match.dev/open-match/pkg/harness/function/golang"
|
||||
internalMmf "open-match.dev/open-match/internal/testing/mmf"
|
||||
)
|
||||
|
||||
func TestMakeMatches(t *testing.T) {
|
||||
@ -72,7 +72,7 @@ func TestMakeMatches(t *testing.T) {
|
||||
"pool2": tickets[2:],
|
||||
}
|
||||
|
||||
p := &mmfHarness.MatchFunctionParams{
|
||||
p := &internalMmf.MatchFunctionParams{
|
||||
Logger: &logrus.Entry{},
|
||||
ProfileName: "test-profile",
|
||||
Rosters: []*pb.Roster{},
|
Reference in New Issue
Block a user