blob: fb7e6370dfabd7ff260e4afcec067f5168fa4a9d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 broker
import (
"crypto/sha1"
"encoding/json"
"math"
"strconv"
"strings"
"time"
"github.com/apache/servicecomb-service-center/pkg/log"
"github.com/apache/servicecomb-service-center/pkg/util"
"github.com/apache/servicecomb-service-center/server/broker/brokerpb"
apt "github.com/apache/servicecomb-service-center/server/core"
pb "github.com/apache/servicecomb-service-center/server/core/proto"
scerr "github.com/apache/servicecomb-service-center/server/error"
"github.com/apache/servicecomb-service-center/server/plugin/pkg/registry"
serviceUtil "github.com/apache/servicecomb-service-center/server/service/util"
"golang.org/x/net/context"
)
var BrokerServiceAPI = &BrokerService{}
type BrokerService struct {
}
func (*BrokerService) GetBrokerHome(ctx context.Context,
in *brokerpb.BaseBrokerRequest) (*brokerpb.BrokerHomeResponse, error) {
if in == nil || len(in.HostAddress) == 0 {
PactLogger.Errorf(nil, "Get Participant versions request failed: invalid params.")
return &brokerpb.BrokerHomeResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Request format invalid."),
}, nil
}
return GetBrokerHomeResponse(in.HostAddress, in.Scheme), nil
}
func (*BrokerService) GetPactsOfProvider(ctx context.Context,
in *brokerpb.GetProviderConsumerVersionPactRequest) (*brokerpb.GetProviderConsumerVersionPactResponse, error) {
PactLogger.Infof("GetPactsOfProvider: (%s, %s, %s)\n",
in.ProviderId, in.ConsumerId, in.Version)
resp, pactId, err := RetrieveProviderConsumerPact(ctx, in)
if err != nil || resp.GetPact() == nil || pactId == -1 {
var message string
if resp != nil {
message = resp.Response.Message
}
PactLogger.Errorf(err, "Get pacts of provider failed: %s\n", message)
return &brokerpb.GetProviderConsumerVersionPactResponse{
Response: resp.GetResponse(),
}, err
}
urlValue := GenerateBrokerAPIPath(in.BaseUrl.Scheme, in.BaseUrl.HostAddress,
BROKER_PUBLISH_VERIFICATION_URL,
strings.NewReplacer(":providerId", in.ProviderId,
":consumerId", in.ConsumerId,
":pact", strconv.FormatInt(int64(pactId), 10)))
links := ",\"_links\": {" +
"\"pb:publish-verification-results\": {" +
"\"title\": \"Publish verification results\"," +
"\"href\": \"" + urlValue +
"\"" +
"}" +
"}}"
linksBytes := []byte(links)
pactBytes := resp.GetPact()
sliceOfResp := pactBytes[0 : len(pactBytes)-2]
finalBytes := append(sliceOfResp, linksBytes...)
return &brokerpb.GetProviderConsumerVersionPactResponse{
Response: pb.CreateResponse(pb.Response_SUCCESS, "Success."),
Pact: finalBytes,
}, nil
//controller.WriteText(http.StatusBadRequest, resp.Response.Message, w)
}
func (*BrokerService) DeletePacts(ctx context.Context,
in *brokerpb.BaseBrokerRequest) (*pb.Response, error) {
resp, err := DeletePactData(ctx, in)
return resp, err
}
func (*BrokerService) RetrieveProviderPacts(ctx context.Context,
in *brokerpb.GetAllProviderPactsRequest) (*brokerpb.GetAllProviderPactsResponse, error) {
if in == nil || len(in.ProviderId) == 0 {
PactLogger.Errorf(nil, "all provider pact retrieve request failed: invalid params.")
return &brokerpb.GetAllProviderPactsResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Request format invalid."),
}, nil
}
tenant := GetDefaultTenantProject()
provider, err := serviceUtil.GetService(ctx, tenant, in.ProviderId)
if err != nil {
PactLogger.Errorf(err, "all provider pact retrieve failed, providerId is %s: query provider failed.", in.ProviderId)
return &brokerpb.GetAllProviderPactsResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Query provider failed."),
}, err
}
if provider == nil {
PactLogger.Errorf(nil, "all provider pact retrieve failed, providerId is %s: provider not exist.", in.ProviderId)
return &brokerpb.GetAllProviderPactsResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Provider does not exist."),
}, nil
}
// Get the provider participant
//providerParticipantKey := apt.GenerateBrokerParticipantKey(tenant, provider.AppId, provider.ServiceName)
providerParticipant, err := GetParticipant(ctx, tenant, provider.AppId, provider.ServiceName)
if err != nil || providerParticipant == nil {
PactLogger.Errorf(nil, "all provider pact retrieve failed, provider participant cannot be searched.", in.ProviderId)
return &brokerpb.GetAllProviderPactsResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Provider participant cannot be searched."),
}, err
}
PactLogger.Infof("[RetrieveProviderPacts] Provider participant id : %d", providerParticipant.Id)
// Get all versions
versionKey := util.StringJoin([]string{GetBrokerVersionKey(tenant), ""}, "/")
versions, err := Store().Version().Search(ctx,
registry.WithPrefix(),
registry.WithStrKey(versionKey))
if err != nil {
return nil, err
}
if len(versions.Kvs) == 0 {
PactLogger.Info("[RetrieveProviderPacts] No versions found, sorry")
return nil, nil
}
// Store versions in a map
versionObjects := make(map[int32]brokerpb.Version)
for i := 0; i < len(versions.Kvs); i++ {
version := &brokerpb.Version{}
err = json.Unmarshal(versions.Kvs[i].Value.([]byte), version)
if err != nil {
return nil, err
}
PactLogger.Infof("[RetrieveProviderPacts] Version found : (%d, %s)", version.Id, version.Number)
versionObjects[version.Id] = *version
}
// Get all pactversions and filter using the provider participant id
pactVersionKey := util.StringJoin([]string{GetBrokerPactVersionKey(tenant), ""}, "/")
pactVersions, err := Store().PactVersion().Search(ctx,
registry.WithStrKey(pactVersionKey),
registry.WithPrefix())
if err != nil {
return nil, err
}
if len(pactVersions.Kvs) == 0 {
PactLogger.Info("[RetrieveProviderPacts] No pact version found, sorry")
return nil, nil
}
participantToVersionObj := make(map[int32]brokerpb.Version)
for i := 0; i < len(pactVersions.Kvs); i++ {
pactVersion := &brokerpb.PactVersion{}
err = json.Unmarshal(pactVersions.Kvs[i].Value.([]byte), pactVersion)
if err != nil {
return nil, err
}
if pactVersion.ProviderParticipantId != providerParticipant.Id {
continue
}
PactLogger.Infof("[RetrieveProviderPacts] Pact version found: (%d, %d, %d, %d)", pactVersion.Id, pactVersion.VersionId, pactVersion.PactId, pactVersion.ProviderParticipantId)
vObj := versionObjects[pactVersion.VersionId]
if v1Obj, ok := participantToVersionObj[vObj.ParticipantId]; ok {
if vObj.Order > v1Obj.Order {
participantToVersionObj[vObj.ParticipantId] = vObj
}
} else {
participantToVersionObj[vObj.ParticipantId] = vObj
}
}
// Get all participants
participantKey := util.StringJoin([]string{GetBrokerParticipantKey(tenant), ""}, "/")
participants, err := Store().Participant().Search(ctx,
registry.WithStrKey(participantKey),
registry.WithPrefix())
if err != nil {
return nil, err
}
if len(participants.Kvs) == 0 {
return nil, nil
}
consumerInfoArr := make([]*brokerpb.ConsumerInfo, 0)
for i := 0; i < len(participants.Kvs); i++ {
participant := &brokerpb.Participant{}
err = json.Unmarshal(participants.Kvs[i].Value.([]byte), participant)
if err != nil {
return nil, err
}
if _, ok := participantToVersionObj[participant.Id]; !ok {
continue
}
PactLogger.Infof("[RetrieveProviderPacts] Consumer found: (%d, %s, %s)", participant.Id, participant.AppId, participant.ServiceName)
consumerVersion := participantToVersionObj[participant.Id].Number
consumerId, err := serviceUtil.GetServiceId(ctx, &pb.MicroServiceKey{
Tenant: tenant,
AppId: participant.AppId,
ServiceName: participant.ServiceName,
Version: consumerVersion,
})
if err != nil {
return nil, err
}
PactLogger.Infof("[RetrieveProviderPacts] Consumer microservice found: %s", consumerId)
urlValue := GenerateBrokerAPIPath(in.BaseUrl.Scheme, in.BaseUrl.HostAddress,
BROKER_PUBLISH_URL,
strings.NewReplacer(":providerId", in.ProviderId,
":consumerId", consumerId,
":number", consumerVersion))
consumerInfo := &brokerpb.ConsumerInfo{
Href: urlValue,
Name: consumerId,
}
consumerInfoArr = append(consumerInfoArr, consumerInfo)
}
links := &brokerpb.Links{
Pacts: consumerInfoArr,
}
resJson, err := json.Marshal(links)
if err != nil {
return nil, err
}
PactLogger.Infof("Json : %s", string(resJson))
response := &brokerpb.GetAllProviderPactsResponse{
Response: pb.CreateResponse(pb.Response_SUCCESS, "retrieve provider pact info succeeded."),
XLinks: links,
}
return response, nil
}
func (*BrokerService) GetAllProviderPacts(ctx context.Context,
in *brokerpb.GetAllProviderPactsRequest) (*brokerpb.GetAllProviderPactsResponse, error) {
if in == nil || len(in.ProviderId) == 0 {
PactLogger.Errorf(nil, "all provider pact retrieve request failed: invalid params.")
return &brokerpb.GetAllProviderPactsResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Request format invalid."),
}, nil
}
tenant := GetDefaultTenantProject()
provider, err := serviceUtil.GetService(ctx, tenant, in.ProviderId)
if err != nil {
PactLogger.Errorf(err, "all provider pact retrieve failed, providerId is %s: query provider failed.", in.ProviderId)
return &brokerpb.GetAllProviderPactsResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Query provider failed."),
}, err
}
if provider == nil {
PactLogger.Errorf(nil, "all provider pact retrieve failed, providerId is %s: provider not exist.", in.ProviderId)
return &brokerpb.GetAllProviderPactsResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Provider does not exist."),
}, nil
}
// Get the provider participant
//providerParticipantKey := apt.GenerateBrokerParticipantKey(tenant, provider.AppId, provider.ServiceName)
providerParticipant, err := GetParticipant(ctx, tenant, provider.AppId, provider.ServiceName)
if err != nil || providerParticipant == nil {
PactLogger.Errorf(nil, "all provider pact retrieve failed, provider participant cannot be searched.", in.ProviderId)
return &brokerpb.GetAllProviderPactsResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Provider participant cannot be searched."),
}, err
}
PactLogger.Infof("[RetrieveProviderPacts] Provider participant id : %d", providerParticipant.Id)
// Get all versions
versionKey := util.StringJoin([]string{GetBrokerVersionKey(tenant), ""}, "/")
versions, err := Store().Version().Search(ctx,
registry.WithPrefix(),
registry.WithStrKey(versionKey))
if err != nil {
return nil, err
}
if len(versions.Kvs) == 0 {
PactLogger.Info("[RetrieveProviderPacts] No versions found, sorry")
return nil, nil
}
// Store versions in a map
versionObjects := make(map[int32]brokerpb.Version)
for i := 0; i < len(versions.Kvs); i++ {
version := &brokerpb.Version{}
err = json.Unmarshal(versions.Kvs[i].Value.([]byte), version)
if err != nil {
return nil, err
}
PactLogger.Infof("[RetrieveProviderPacts] Version found : (%d, %s)", version.Id, version.Number)
versionObjects[version.Id] = *version
}
// Get all pactversions and filter using the provider participant id
pactVersionKey := util.StringJoin([]string{GetBrokerPactVersionKey(tenant), ""}, "/")
pactVersions, err := Store().PactVersion().Search(ctx,
registry.WithStrKey(pactVersionKey),
registry.WithPrefix())
if err != nil {
return nil, err
}
if len(pactVersions.Kvs) == 0 {
PactLogger.Info("[RetrieveProviderPacts] No pact version found, sorry")
return nil, nil
}
participantToVersionObj := make(map[int32]brokerpb.Version)
for i := 0; i < len(pactVersions.Kvs); i++ {
pactVersion := &brokerpb.PactVersion{}
err = json.Unmarshal(pactVersions.Kvs[i].Value.([]byte), pactVersion)
if err != nil {
return nil, err
}
if pactVersion.ProviderParticipantId != providerParticipant.Id {
continue
}
PactLogger.Infof("[RetrieveProviderPacts] Pact version found: (%d, %d, %d, %d)", pactVersion.Id, pactVersion.VersionId, pactVersion.PactId, pactVersion.ProviderParticipantId)
vObj := versionObjects[pactVersion.VersionId]
if v1Obj, ok := participantToVersionObj[vObj.ParticipantId]; ok {
if vObj.Order > v1Obj.Order {
participantToVersionObj[vObj.ParticipantId] = vObj
}
} else {
participantToVersionObj[vObj.ParticipantId] = vObj
}
}
// Get all participants
participantKey := util.StringJoin([]string{GetBrokerParticipantKey(tenant), ""}, "/")
participants, err := Store().Participant().Search(ctx,
registry.WithStrKey(participantKey),
registry.WithPrefix())
if err != nil {
return nil, err
}
if len(participants.Kvs) == 0 {
return nil, nil
}
consumerInfoArr := make([]*brokerpb.ConsumerInfo, 0)
for i := 0; i < len(participants.Kvs); i++ {
participant := &brokerpb.Participant{}
err = json.Unmarshal(participants.Kvs[i].Value.([]byte), participant)
if err != nil {
return nil, err
}
if _, ok := participantToVersionObj[participant.Id]; !ok {
continue
}
PactLogger.Infof("[RetrieveProviderPacts] Consumer found: (%d, %s, %s)", participant.Id, participant.AppId, participant.ServiceName)
consumerVersion := participantToVersionObj[participant.Id].Number
consumerId, err := serviceUtil.GetServiceId(ctx, &pb.MicroServiceKey{
Tenant: tenant,
AppId: participant.AppId,
ServiceName: participant.ServiceName,
Version: consumerVersion,
})
if err != nil {
return nil, err
}
PactLogger.Infof("[RetrieveProviderPacts] Consumer microservice found: %s", consumerId)
urlValue := GenerateBrokerAPIPath(in.BaseUrl.Scheme, in.BaseUrl.HostAddress,
BROKER_PUBLISH_URL,
strings.NewReplacer(":providerId", in.ProviderId,
":consumerId", consumerId,
":number", consumerVersion))
consumerInfo := &brokerpb.ConsumerInfo{
Href: urlValue,
Name: consumerId,
}
consumerInfoArr = append(consumerInfoArr, consumerInfo)
}
links := &brokerpb.Links{
Pacts: consumerInfoArr,
}
resJson, err := json.Marshal(links)
if err != nil {
return nil, err
}
PactLogger.Infof("Json : %s", string(resJson))
response := &brokerpb.GetAllProviderPactsResponse{
Response: pb.CreateResponse(pb.Response_SUCCESS, "retrieve provider pact info succeeded."),
XLinks: links,
}
return response, nil
}
func (*BrokerService) RetrieveVerificationResults(ctx context.Context, in *brokerpb.RetrieveVerificationRequest) (*brokerpb.RetrieveVerificationResponse, error) {
if in == nil || len(in.ConsumerId) == 0 || len(in.ConsumerVersion) == 0 {
PactLogger.Errorf(nil, "verification result retrieve request failed: invalid params.")
return &brokerpb.RetrieveVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Request format invalid."),
}, nil
}
tenant := GetDefaultTenantProject()
consumer, err := serviceUtil.GetService(ctx, tenant, in.ConsumerId)
if err != nil {
PactLogger.Errorf(err, "verification result retrieve request failed, consumerId is %s: query consumer failed.", in.ConsumerId)
return &brokerpb.RetrieveVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Query consumer failed."),
}, err
}
if consumer == nil {
PactLogger.Errorf(nil, "verification result retrieve request failed, consumerId is %s: consumer not exist.", in.ConsumerId)
return &brokerpb.RetrieveVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Consumer does not exist."),
}, nil
}
PactLogger.Infof("Consumer service found: (%s, %s, %s, %s)", consumer.ServiceId, consumer.AppId, consumer.ServiceName, consumer.Version)
// Get consumer participant
consumerParticipant, err := GetParticipant(ctx, tenant, consumer.AppId, consumer.ServiceName)
if err != nil || consumerParticipant == nil {
PactLogger.Errorf(nil, "verification result retrieve request failed, consumer participant cannot be searched.", in.ConsumerId)
return &brokerpb.RetrieveVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "consumer participant cannot be searched."),
}, err
}
PactLogger.Infof("Consumer participant found: (%d, %s, %s)", consumerParticipant.Id, consumerParticipant.AppId, consumerParticipant.ServiceName)
// Get version
version, err := GetVersion(ctx, tenant, consumer.Version, consumerParticipant.Id)
if err != nil || version == nil {
PactLogger.Errorf(nil, "verification result retrieve request failed, version cannot be searched.")
return &brokerpb.RetrieveVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "version cannot be searched."),
}, err
}
PactLogger.Infof("Version found/created: (%d, %s, %d, %d)", version.Id, version.Number, version.ParticipantId, version.Order)
key := util.StringJoin([]string{GetBrokerPactVersionKey(tenant), strconv.Itoa(int(version.Id))}, "/")
pactVersions, err := Store().PactVersion().Search(ctx,
registry.WithPrefix(),
registry.WithStrKey(key))
if err != nil || len(pactVersions.Kvs) == 0 {
PactLogger.Errorf(nil, "verification result publish request failed, pact version cannot be searched.")
return &brokerpb.RetrieveVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "pact version cannot be searched."),
}, err
}
overAllSuccess := false
successfuls := make([]string, 0)
fails := make([]string, 0)
unknowns := make([]string, 0)
verificationDetailsArr := make([]*brokerpb.VerificationDetail, 0)
for j := 0; j < len(pactVersions.Kvs); j++ {
pactVersion := &brokerpb.PactVersion{}
err = json.Unmarshal(pactVersions.Kvs[j].Value.([]byte), &pactVersion)
if err != nil {
PactLogger.Errorf(nil, "verification result retrieve request failed, pact version cannot be searched.")
return &brokerpb.RetrieveVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "pact version cannot be searched."),
}, err
}
key = util.StringJoin([]string{GetBrokerVerificationKey(tenant), strconv.Itoa(int(pactVersion.Id))}, "/")
verifications, err := Store().Verification().Search(ctx,
registry.WithPrefix(),
registry.WithStrKey(key))
if err != nil || len(verifications.Kvs) == 0 {
PactLogger.Errorf(nil, "verification result retrieve request failed, verification results cannot be searched.")
return &brokerpb.RetrieveVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "verification results cannot be searched."),
}, err
}
lastNumber := int32(math.MinInt32)
var lastVerificationResult *brokerpb.Verification
for i := 0; i < len(verifications.Kvs); i++ {
verification := &brokerpb.Verification{}
err = json.Unmarshal(verifications.Kvs[i].Value.([]byte), &verification)
if err != nil {
PactLogger.Errorf(nil, "verification result retrieve request failed, verification result unmarshall error.")
return &brokerpb.RetrieveVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "verification result unmarshall error."),
}, err
}
if verification.Number > lastNumber {
lastNumber = verification.Number
lastVerificationResult = verification
}
}
if lastVerificationResult == nil {
PactLogger.Errorf(nil, "verification result retrieve request failed, verification result cannot be found.")
return &brokerpb.RetrieveVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "verification result cannot be found."),
}, err
}
PactLogger.Infof("Verification result found: (%d, %d, %d, %t, %s, %s, %s)",
lastVerificationResult.Id, lastVerificationResult.Number, lastVerificationResult.PactVersionId,
lastVerificationResult.Success, lastVerificationResult.ProviderVersion,
lastVerificationResult.BuildUrl, lastVerificationResult.VerificationDate)
key = util.StringJoin([]string{GetBrokerParticipantKey(tenant), ""}, "/")
participants, err := Store().Participant().Search(ctx,
registry.WithStrKey(key),
registry.WithPrefix())
if err != nil || len(participants.Kvs) == 0 {
PactLogger.Errorf(nil, "verification result retrieve request failed, provider participant cannot be searched.")
return &brokerpb.RetrieveVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "provider participant cannot be searched."),
}, err
}
var providerParticipant *brokerpb.Participant
for i := 0; i < len(participants.Kvs); i++ {
participant := &brokerpb.Participant{}
err = json.Unmarshal(participants.Kvs[i].Value.([]byte), &participant)
if err != nil {
PactLogger.Errorf(nil, "verification result retrieve request failed, verification result unmarshall error.")
return &brokerpb.RetrieveVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "verification result unmarshall error."),
}, err
}
if participant.Id == pactVersion.ProviderParticipantId {
providerParticipant = participant
break
}
}
if providerParticipant == nil {
PactLogger.Errorf(nil, "verification result retrieve request failed, verification result unmarshall error.")
return &brokerpb.RetrieveVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "verification result unmarshall error."),
}, err
}
serviceFindReq := &pb.GetExistenceRequest{
Type: "microservice",
AppId: providerParticipant.AppId,
ServiceName: providerParticipant.ServiceName,
Version: lastVerificationResult.ProviderVersion,
}
resp, err := apt.ServiceAPI.Exist(ctx, serviceFindReq)
if err != nil {
PactLogger.Errorf(nil, "verification result retrieve request failed, provider service cannot be found.")
return &brokerpb.RetrieveVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "provider service cannot be found."),
}, err
}
providerName := resp.ServiceId
verificationDetail := &brokerpb.VerificationDetail{
ProviderName: providerName,
ProviderApplicationVersion: lastVerificationResult.ProviderVersion,
Success: lastVerificationResult.Success,
VerificationDate: lastVerificationResult.VerificationDate,
}
verificationDetailsArr = append(verificationDetailsArr, verificationDetail)
if verificationDetail.Success == true {
successfuls = append(successfuls, providerName)
} else {
fails = append(fails, providerName)
}
overAllSuccess = overAllSuccess && verificationDetail.Success
}
verificationDetails := &brokerpb.VerificationDetails{VerificationResults: verificationDetailsArr}
verificationSummary := &brokerpb.VerificationSummary{Successful: successfuls, Failed: fails, Unknown: unknowns}
verificationResult := &brokerpb.VerificationResult{Success: overAllSuccess, ProviderSummary: verificationSummary, XEmbedded: verificationDetails}
PactLogger.Infof("Verification result retrieved successfully ...")
return &brokerpb.RetrieveVerificationResponse{
Response: pb.CreateResponse(pb.Response_SUCCESS, "Verification result retrieved successfully."),
Result: verificationResult,
}, nil
}
func (*BrokerService) PublishVerificationResults(ctx context.Context, in *brokerpb.PublishVerificationRequest) (*brokerpb.PublishVerificationResponse, error) {
if in == nil || len(in.ProviderId) == 0 || len(in.ConsumerId) == 0 {
PactLogger.Errorf(nil, "verification result publish request failed: invalid params.")
return &brokerpb.PublishVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Request format invalid."),
}, nil
}
tenant := GetDefaultTenantProject()
consumer, err := serviceUtil.GetService(ctx, tenant, in.ConsumerId)
if err != nil {
PactLogger.Errorf(err, "verification result publish request failed, consumerId is %s: query consumer failed.", in.ConsumerId)
return &brokerpb.PublishVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Query consumer failed."),
}, err
}
if consumer == nil {
PactLogger.Errorf(nil, "verification result publish request failed, consumerId is %s: consumer not exist.", in.ConsumerId)
return &brokerpb.PublishVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Consumer does not exist."),
}, nil
}
PactLogger.Infof("Consumer service found: (%s, %s, %s, %s)", consumer.ServiceId, consumer.AppId, consumer.ServiceName, consumer.Version)
// Get consumer participant
consumerParticipant, err := GetParticipant(ctx, tenant, consumer.AppId, consumer.ServiceName)
if err != nil || consumerParticipant == nil {
PactLogger.Errorf(nil, "verification result publish request failed, consumer participant cannot be searched.", in.ConsumerId)
return &brokerpb.PublishVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "consumer participant cannot be searched."),
}, err
}
PactLogger.Infof("Consumer participant found: (%d, %s, %s)", consumerParticipant.Id, consumerParticipant.AppId, consumerParticipant.ServiceName)
// Get version
version, err := GetVersion(ctx, tenant, consumer.Version, consumerParticipant.Id)
if err != nil || version == nil {
PactLogger.Errorf(nil, "verification result publish request failed, version cannot be searched.")
return &brokerpb.PublishVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "version cannot be searched."),
}, err
}
PactLogger.Infof("Version found/created: (%d, %s, %d, %d)", version.Id, version.Number, version.ParticipantId, version.Order)
key := util.StringJoin([]string{GetBrokerPactKey(tenant), ""}, "/")
pacts, err := Store().Pact().Search(ctx,
registry.WithStrKey(key),
registry.WithPrefix())
if err != nil || len(pacts.Kvs) == 0 {
PactLogger.Errorf(nil, "verification result publish request failed, pact cannot be searched.")
return &brokerpb.PublishVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "pact cannot be searched."),
}, err
}
pactExists := false
for i := 0; i < len(pacts.Kvs); i++ {
pact := &brokerpb.Pact{}
err = json.Unmarshal(pacts.Kvs[i].Value.([]byte), &pact)
if err != nil {
PactLogger.Errorf(nil, "verification result publish request failed, pact cannot be searched.")
return &brokerpb.PublishVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "pact cannot be searched."),
}, err
}
if pact.Id == in.PactId {
pactExists = true
}
}
if pactExists == false {
PactLogger.Errorf(nil, "verification result publish request failed, pact does not exists.")
return &brokerpb.PublishVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "pact does not exists."),
}, err
}
pactVersion, err := GetPactVersion(ctx, tenant, version.Id, in.PactId)
if err != nil || pactVersion == nil {
PactLogger.Errorf(nil, "verification result publish request failed, pact version cannot be searched.")
return &brokerpb.PublishVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "pact version cannot be searched."),
}, err
}
// Check if some verification results already exists
key = util.StringJoin([]string{GetBrokerVerificationKey(tenant), strconv.Itoa(int(pactVersion.Id))}, "/")
verifications, err := Store().Verification().Search(ctx,
registry.WithStrKey(key),
registry.WithPrefix())
if err != nil {
PactLogger.Errorf(nil, "verification result publish request failed, verification result cannot be searched.")
return &brokerpb.PublishVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "verification result cannot be searched."),
}, err
}
lastNumber := int32(math.MinInt32)
if len(verifications.Kvs) != 0 {
for i := 0; i < len(verifications.Kvs); i++ {
verification := &brokerpb.Verification{}
err = json.Unmarshal(verifications.Kvs[i].Value.([]byte), &verification)
if err != nil {
PactLogger.Errorf(nil, "verification result publish request failed, verification result unmarshall error.")
return &brokerpb.PublishVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "verification result unmarshall error."),
}, err
}
if verification.Number > lastNumber {
lastNumber = verification.Number
}
}
}
if lastNumber < 0 {
lastNumber = 0
} else {
lastNumber++
}
verificationDate := time.Now().Format(time.RFC3339)
verificationKey := GenerateBrokerVerificationKey(tenant, pactVersion.Id, lastNumber)
id, err := GetData(ctx, GetBrokerLatestVerificationIDKey())
if err != nil {
return &brokerpb.PublishVerificationResponse{
Response: pb.CreateResponse(scerr.ErrInternal, "get data error."),
}, err
}
verification := &brokerpb.Verification{
Id: int32(id) + 1,
Number: lastNumber,
PactVersionId: pactVersion.Id,
Success: in.Success,
ProviderVersion: in.ProviderApplicationVersion,
BuildUrl: "",
VerificationDate: verificationDate,
}
response, err := CreateVerification(PactLogger, ctx, verificationKey, *verification)
if err != nil {
return response, err
}
PactLogger.Infof("Verification result inserted: (%d, %d, %d, %t, %s, %s, %s)",
verification.Id, verification.Number, verification.PactVersionId,
verification.Success, verification.ProviderVersion, verification.BuildUrl, verification.VerificationDate)
verificationResponse := &brokerpb.VerificationDetail{
ProviderName: in.ProviderId,
ProviderApplicationVersion: verification.ProviderVersion,
Success: verification.Success,
VerificationDate: verification.VerificationDate,
}
PactLogger.Infof("Verification result published successfully ...")
return &brokerpb.PublishVerificationResponse{
Response: pb.CreateResponse(pb.Response_SUCCESS, "Verification result published successfully."),
Confirmation: verificationResponse,
}, nil
}
func (*BrokerService) PublishPact(ctx context.Context, in *brokerpb.PublishPactRequest) (*brokerpb.PublishPactResponse, error) {
if in == nil || len(in.ProviderId) == 0 || len(in.ConsumerId) == 0 || len(in.Version) == 0 || len(in.Pact) == 0 {
PactLogger.Errorf(nil, "pact publish request failed: invalid params.")
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Request format invalid."),
}, nil
}
tenant := GetDefaultTenantProject()
provider, err := serviceUtil.GetService(ctx, tenant, in.ProviderId)
if err != nil {
PactLogger.Errorf(err, "pact publish failed, providerId is %s: query provider failed.", in.ProviderId)
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Query provider failed."),
}, err
}
if provider == nil {
PactLogger.Errorf(nil, "pact publish failed, providerId is %s: provider not exist.", in.ProviderId)
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Provider does not exist."),
}, nil
}
PactLogger.Infof("Provider service found: (%s, %s, %s, %s)", provider.ServiceId, provider.AppId, provider.ServiceName, provider.Version)
consumer, err := serviceUtil.GetService(ctx, tenant, in.ConsumerId)
if err != nil {
PactLogger.Errorf(err, "pact publish failed, consumerId is %s: query consumer failed.", in.ConsumerId)
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Query consumer failed."),
}, err
}
if consumer == nil {
PactLogger.Errorf(nil, "pact publish failed, consumerId is %s: consumer not exist.", in.ConsumerId)
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Consumer does not exist."),
}, nil
}
// check that the consumer has that vesion in the url
if strings.Compare(consumer.GetVersion(), in.Version) != 0 {
log.Errorf(nil,
"pact publish failed, version (%s) does not exist for consmer", in.Version)
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Consumer Version does not exist."),
}, nil
}
PactLogger.Infof("Consumer service found: (%s, %s, %s, %s)", consumer.ServiceId, consumer.AppId, consumer.ServiceName, consumer.Version)
// Get or create provider participant
providerParticipantKey := GenerateBrokerParticipantKey(tenant, provider.AppId, provider.ServiceName)
providerParticipant, err := GetParticipant(ctx, tenant, provider.AppId, provider.ServiceName)
if err != nil {
PactLogger.Errorf(nil, "pact publish failed, provider participant cannot be searched.", in.ProviderId)
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "Provider participant cannot be searched."),
}, err
}
if providerParticipant == nil {
id, err := GetData(ctx, GetBrokerLatestParticipantIDKey())
if err != nil {
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInternal, "get data error."),
}, err
}
providerParticipant = &brokerpb.Participant{Id: int32(id) + 1, AppId: provider.AppId, ServiceName: provider.ServiceName}
response, err := CreateParticipant(PactLogger, ctx, providerParticipantKey, *providerParticipant)
if err != nil {
return response, err
}
}
PactLogger.Infof("Provider participant found: (%d, %s, %s)", providerParticipant.Id, providerParticipant.AppId, providerParticipant.ServiceName)
// Get or create consumer participant
consumerParticipantKey := GenerateBrokerParticipantKey(tenant, consumer.AppId, consumer.ServiceName)
consumerParticipant, err := GetParticipant(ctx, tenant, consumer.AppId, consumer.ServiceName)
if err != nil {
PactLogger.Errorf(nil, "pact publish failed, consumer participant cannot be searched.", in.ConsumerId)
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "consumer participant cannot be searched."),
}, err
}
if consumerParticipant == nil {
id, err := GetData(ctx, GetBrokerLatestParticipantIDKey())
if err != nil {
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInternal, "get data error."),
}, err
}
consumerParticipant = &brokerpb.Participant{Id: int32(id) + 1, AppId: consumer.AppId, ServiceName: consumer.ServiceName}
response, err := CreateParticipant(PactLogger, ctx, consumerParticipantKey, *consumerParticipant)
if err != nil {
return response, err
}
}
PactLogger.Infof("Consumer participant found: (%d, %s, %s)", consumerParticipant.Id, consumerParticipant.AppId, consumerParticipant.ServiceName)
// Get or create version
versionKey := GenerateBrokerVersionKey(tenant, in.Version, consumerParticipant.Id)
version, err := GetVersion(ctx, tenant, in.Version, consumerParticipant.Id)
if err != nil {
PactLogger.Errorf(nil, "pact publish failed, version cannot be searched.")
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "version cannot be searched."),
}, err
}
if version == nil {
order := GetLastestVersionNumberForParticipant(ctx, tenant, consumerParticipant.Id)
PactLogger.Infof("Old version order: %d", order)
order++
id, err := GetData(ctx, GetBrokerLatestVersionIDKey())
if err != nil {
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInternal, "get data error."),
}, err
}
version = &brokerpb.Version{Id: int32(id) + 1, Number: in.Version, ParticipantId: consumerParticipant.Id, Order: order}
response, err := CreateVersion(PactLogger, ctx, versionKey, *version)
if err != nil {
return response, err
}
}
PactLogger.Infof("Version found/created: (%d, %s, %d, %d)", version.Id, version.Number, version.ParticipantId, version.Order)
// Get or create pact
sha1 := sha1.Sum(in.Pact)
var sha []byte = sha1[:]
pactKey := GenerateBrokerPactKey(tenant, consumerParticipant.Id, providerParticipant.Id, sha)
pact, err := GetPact(ctx, tenant, consumerParticipant.Id, providerParticipant.Id, sha)
if err != nil {
PactLogger.Errorf(nil, "pact publish failed, pact cannot be searched.")
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "pact cannot be searched."),
}, err
}
if pact == nil {
id, err := GetData(ctx, GetBrokerLatestPactIDKey())
if err != nil {
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInternal, "get data error."),
}, err
}
pact = &brokerpb.Pact{Id: int32(id) + 1, ConsumerParticipantId: consumerParticipant.Id,
ProviderParticipantId: providerParticipant.Id, Sha: sha, Content: in.Pact}
response, err := CreatePact(PactLogger, ctx, pactKey, *pact)
if err != nil {
return response, err
}
}
PactLogger.Infof("Pact found/created: (%d, %d, %d, %s)", pact.Id, pact.ConsumerParticipantId, pact.ProviderParticipantId, pact.Sha)
// Get or create pact version
pactVersionKey := GenerateBrokerPactVersionKey(tenant, version.Id, pact.Id)
pactVersion, err := GetPactVersion(ctx, tenant, version.Id, pact.Id)
if err != nil {
PactLogger.Errorf(nil, "pact publish failed, pact version cannot be searched.")
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInvalidParams, "pact version cannot be searched."),
}, err
}
if pactVersion == nil {
id, err := GetData(ctx, GetBrokerLatestPactVersionIDKey())
if err != nil {
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(scerr.ErrInternal, "get data error."),
}, err
}
pactVersion = &brokerpb.PactVersion{Id: int32(id) + 1, VersionId: version.Id, PactId: pact.Id, ProviderParticipantId: providerParticipant.Id}
response, err := CreatePactVersion(PactLogger, ctx, pactVersionKey, *pactVersion)
if err != nil {
return response, err
}
}
PactLogger.Infof("PactVersion found/create: (%d, %d, %d, %d)", pactVersion.Id, pactVersion.VersionId, pactVersion.PactId, pactVersion.ProviderParticipantId)
PactLogger.Infof("Pact published successfully ...")
return &brokerpb.PublishPactResponse{
Response: pb.CreateResponse(pb.Response_SUCCESS, "Pact published successfully."),
}, nil
}