| /* |
| * 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 |
| } |