Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/docker/golang-1.23.3
Browse files Browse the repository at this point in the history
  • Loading branch information
MR2011 authored Nov 11, 2024
2 parents 18b99f9 + 4503955 commit 92bf32d
Show file tree
Hide file tree
Showing 11 changed files with 473 additions and 42 deletions.
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ require (
github.com/samber/lo v1.47.0
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.9.0
github.com/vektah/gqlparser/v2 v2.5.18
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0
)
Expand All @@ -39,7 +38,7 @@ require (
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/distribution/reference v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
Expand All @@ -50,6 +49,7 @@ require (
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/goark/errs v1.3.2 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
Expand All @@ -64,7 +64,6 @@ require (
github.com/leodido/go-urn v1.4.0 // indirect
github.com/matryer/is v1.4.1 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
Expand All @@ -85,7 +84,8 @@ require (
github.com/stretchr/objx v0.5.2 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/urfave/cli/v2 v2.27.4 // indirect
github.com/urfave/cli/v2 v2.27.5 // indirect
github.com/vektah/gqlparser/v2 v2.5.19 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
Expand All @@ -108,7 +108,7 @@ require (
)

require (
github.com/99designs/gqlgen v0.17.55
github.com/99designs/gqlgen v0.17.56
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/go-sql-driver/mysql v1.8.1
Expand Down
20 changes: 10 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/99designs/gqlgen v0.17.55 h1:3vzrNWYyzSZjGDFo68e5j9sSauLxfKvLp+6ioRokVtM=
github.com/99designs/gqlgen v0.17.55/go.mod h1:3Bq768f8hgVPGZxL8aY9MaYmbxa6llPM/qu1IGH1EJo=
github.com/99designs/gqlgen v0.17.56 h1:+J42ARAHvnysH6klO9Wq+tCsGF32cpAgU3SyF0VRJtI=
github.com/99designs/gqlgen v0.17.56/go.mod h1:rmB6vLvtL8uf9F9w0/irJ5alBkD8DJvj35ET31BKbtY=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
Expand Down Expand Up @@ -36,8 +36,8 @@ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -80,6 +80,8 @@ github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpv
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/goark/errs v1.3.2 h1:ifccNe1aK7Xezt4XVYwHUqalmnfhuphnEvh3FshCReQ=
github.com/goark/errs v1.3.2/go.mod h1:ZsQucxaDFVfSB8I99j4bxkDRfNOrlKINwg72QMuRWKw=
github.com/goark/go-cvss v1.6.7 h1:9R/cx8+lv17uFS1RKYNmEfYqEJwWgF26F4g7hK38jEw=
Expand Down Expand Up @@ -140,8 +142,6 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
Expand Down Expand Up @@ -215,10 +215,10 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8=
github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ=
github.com/vektah/gqlparser/v2 v2.5.18 h1:zSND3GtutylAQ1JpWnTHcqtaRZjl+y3NROeW8vuNo6Y=
github.com/vektah/gqlparser/v2 v2.5.18/go.mod h1:6HLzf7JKv9Fi3APymudztFQNmLXR5qJeEo6BOFcXVfc=
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/vektah/gqlparser/v2 v2.5.19 h1:bhCPCX1D4WWzCDvkPl4+TP1N8/kLrWnp43egplt7iSg=
github.com/vektah/gqlparser/v2 v2.5.19/go.mod h1:y7kvl5bBlDeuWIvLtA9849ncyvx6/lj06RsMrEjVy3U=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
Expand Down
6 changes: 6 additions & 0 deletions internal/app/heureka.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ func (h *HeurekaApp) SubscribeHandlers() {
issue_repository.CreateIssueRepositoryEventName,
event.EventHandlerFunc(issue_repository.OnIssueRepositoryCreate),
)

// Event handlers for ComponentVersion attachments to Issues
h.eventRegistry.RegisterEventHandler(
issue.AddComponentVersionToIssueEventName,
event.EventHandlerFunc(issue.OnComponentVersionAttachmentToIssue),
)
}

func (h *HeurekaApp) Shutdown() error {
Expand Down
97 changes: 97 additions & 0 deletions internal/app/issue/issue_handler_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ package issue

import (
"github.com/cloudoperators/heureka/internal/app/event"
"github.com/cloudoperators/heureka/internal/app/shared"
"github.com/cloudoperators/heureka/internal/database"
"github.com/cloudoperators/heureka/internal/entity"
"github.com/sirupsen/logrus"
"time"
)

const (
Expand Down Expand Up @@ -89,3 +93,96 @@ type ListIssueNamesEvent struct {
func (e *ListIssueNamesEvent) Name() event.EventName {
return ListIssueNamesEventName
}

// OnComponentVersionAttachmentToIssue is an event handler whenever a ComponentVersion
// is attached to an Issue.
func OnComponentVersionAttachmentToIssue(db database.Database, e event.Event) {
l := logrus.WithFields(logrus.Fields{
"event": "OnComponentVersionAttachmentToIssue",
"payload": e,
})

if attachmentEvent, ok := e.(*AddComponentVersionToIssueEvent); ok {
// Get ComponentInstances
l.WithField("event-step", "GetComponentInstances").Debug("Get Component Instances by ComponentVersionId")
componentInstances, err := db.GetComponentInstances(&entity.ComponentInstanceFilter{
ComponentVersionId: []*int64{&attachmentEvent.ComponentVersionID},
})

if err != nil {
l.WithField("event-step", "GetComponentInstances").WithError(err).Error("Error while fetching ComponentInstances")
return
}

// For each ComponentInstance get available IssueVariants
// via GetServiceIssueVariants
for _, compInst := range componentInstances {
// Get Service Issue Variants
issueVariantMap, err := shared.BuildIssueVariantMap(db, &entity.ServiceIssueVariantFilter{
ComponentInstanceId: []*int64{&compInst.Id},
IssueId: []*int64{&attachmentEvent.IssueID},
}, attachmentEvent.ComponentVersionID)
if err != nil {
l.WithField("event-step", "FetchIssueVariants").WithError(err).Error("Error while fetching issue variants")
}

// Create new IssueMatches
createIssueMatches(db, l, compInst.Id, issueVariantMap)
}
} else {
l.Error("Invalid event type received")
}

}

// TODO: This function is very similar to the one used in issue_match_handler_events.go
// We might as well put this into the shared package
//
// createIssueMatches creates new issue matches based on the component instance Id,
// issue ID and their corresponding issue variants (sorted by priority)
func createIssueMatches(
db database.Database,
l *logrus.Entry,
componentInstanceId int64,
issueVariantMap map[int64]entity.ServiceIssueVariant,
) {
for issueId, issueVariant := range issueVariantMap {
l = l.WithFields(logrus.Fields{
"issue": issueVariant,
})

// Check if IssueMatches already exist
l.WithField("event-step", "GetIssueMatches").Debug("Fetching issue matches related to assigned Component Instance")
issue_matches, err := db.GetIssueMatches(&entity.IssueMatchFilter{
IssueId: []*int64{&issueId},
ComponentInstanceId: []*int64{&componentInstanceId},
})

if err != nil {
l.WithField("event-step", "FetchIssueMatches").WithError(err).Error("Error while fetching issue matches related to assigned Component Instance")
}
l.WithField("issueMatchesCount", len(issue_matches))

if len(issue_matches) != 0 {
l.WithField("event-step", "Skipping").Debug("The issue match does already exist. Skipping")
continue
}

// Create new issue match
issue_match := &entity.IssueMatch{
UserId: 1,
Status: entity.IssueMatchStatusValuesNew,
Severity: issueVariantMap[issueId].Severity, //we got two simply take the first one
ComponentInstanceId: componentInstanceId,
IssueId: issueId,
TargetRemediationDate: shared.GetTargetRemediationTimeline(issueVariant.Severity, time.Now(), nil),
}
l.WithField("event-step", "CreateIssueMatch").WithField("issueMatch", issue_match).Debug("Creating Issue Match")

_, err = db.CreateIssueMatch(issue_match)
if err != nil {
l.WithField("event-step", "CreateIssueMatch").WithError(err).Error("Error while creating issue match")
continue
}
}
}
131 changes: 131 additions & 0 deletions internal/app/issue/issue_handler_events_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Greenhouse contributors
// SPDX-License-Identifier: Apache-2.0
package issue_test

import (
"github.com/cloudoperators/heureka/internal/app/issue"

"github.com/cloudoperators/heureka/internal/entity"
"github.com/cloudoperators/heureka/internal/entity/test"
"github.com/cloudoperators/heureka/internal/mocks"
. "github.com/onsi/ginkgo/v2"
"github.com/stretchr/testify/mock"
)

// matchIssueMatch creates a more precise matcher for IssueMatch objects
func matchIssueMatch(expected *entity.IssueMatch) interface{} {
return mock.MatchedBy(func(actual *entity.IssueMatch) bool {
// Basic field matching
basicMatch := actual.Status == expected.Status &&
actual.UserId == expected.UserId &&
actual.ComponentInstanceId == expected.ComponentInstanceId &&
actual.IssueId == expected.IssueId

// Severity matching
severityMatch := actual.Severity.Value == expected.Severity.Value &&
actual.Severity.Score == expected.Severity.Score

return basicMatch && severityMatch
})
}

var _ = Describe("OnComponentVersionAttachmentToIssue", Label("app", "ComponentVersionAttachment"), func() {
var (
db *mocks.MockDatabase
componentVersion entity.ComponentVersion
issueEntity entity.Issue
issueVariant entity.IssueVariant
serviceIssueVariant entity.ServiceIssueVariant
event *issue.AddComponentVersionToIssueEvent
)

BeforeEach(func() {
db = mocks.NewMockDatabase(GinkgoT())

// Setup base test data
componentVersion = test.NewFakeComponentVersionEntity()

// Setup issue
issueEntity = test.NewFakeIssueEntity()
issueEntity.Id = 625000

// Setup issueVariant
issueVariant = test.NewFakeIssueVariantEntity(nil)
issueVariant.IssueId = issueEntity.Id

// Setup serviceIssueVariant
serviceIssueVariant = test.NewFakeServiceIssueVariantEntity(10, &issueEntity.Id)
serviceIssueVariant.Severity = entity.Severity{
Value: "Medium",
Score: 4.5,
Cvss: entity.Cvss{
Vector: "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:N/E:F/RL:O/RC:U",
},
}

event = &issue.AddComponentVersionToIssueEvent{
IssueID: issueEntity.Id,
ComponentVersionID: componentVersion.Id,
}
})

Context("when handling a single component instance", func() {
var componentInstance entity.ComponentInstance

BeforeEach(func() {
componentInstance = test.NewFakeComponentInstanceEntity()
componentInstance.Id = 58708
componentInstance.ComponentVersionId = componentVersion.Id

// // Setup mock expectations for happy path
db.On("GetComponentInstances", &entity.ComponentInstanceFilter{
ComponentVersionId: []*int64{&componentVersion.Id},
}).Return([]entity.ComponentInstance{componentInstance}, nil)
})

It("creates an issue match for the component instance", func() {
// Setup expectation for existing match check
db.On("GetIssueMatches", &entity.IssueMatchFilter{
ComponentInstanceId: []*int64{&componentInstance.Id},
IssueId: []*int64{&issueEntity.Id},
}).Return([]entity.IssueMatch{}, nil)

db.On("GetServiceIssueVariants", &entity.ServiceIssueVariantFilter{
ComponentInstanceId: []*int64{&componentInstance.Id},
IssueId: []*int64{&issueEntity.Id},
}).Return([]entity.ServiceIssueVariant{serviceIssueVariant}, nil)

expectedMatch := &entity.IssueMatch{
UserId: 1,
Status: entity.IssueMatchStatusValuesNew,
Severity: serviceIssueVariant.Severity,
ComponentInstanceId: componentInstance.Id,
IssueId: issueEntity.Id,
}
db.On("CreateIssueMatch", matchIssueMatch(expectedMatch)).Return(expectedMatch, nil)

// Emit event
issue.OnComponentVersionAttachmentToIssue(db, event)

// Assert expectations
db.AssertExpectations(GinkgoT())
})

It("skips creation if match already exists", func() {
existingMatch := test.NewFakeIssueMatch()
db.On("GetServiceIssueVariants", &entity.ServiceIssueVariantFilter{
ComponentInstanceId: []*int64{&componentInstance.Id},
IssueId: []*int64{&issueEntity.Id},
}).Return([]entity.ServiceIssueVariant{serviceIssueVariant}, nil)

// Setup expectation to return existing match
db.On("GetIssueMatches", &entity.IssueMatchFilter{
ComponentInstanceId: []*int64{&componentInstance.Id},
IssueId: []*int64{&issueEntity.Id},
}).Return([]entity.IssueMatch{existingMatch}, nil)

issue.OnComponentVersionAttachmentToIssue(db, event)
db.AssertNotCalled(GinkgoT(), "CreateIssueMatch", mock.Anything)
})
})
})
Loading

0 comments on commit 92bf32d

Please sign in to comment.