Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ require (
github.com/elazarl/goproxy v1.8.0
github.com/fluxcd/cli-utils v0.37.1-flux.1
github.com/fluxcd/notification-controller/api v1.7.0
github.com/fluxcd/pkg/apis/event v0.23.0
github.com/fluxcd/pkg/apis/event v0.24.0
github.com/fluxcd/pkg/apis/meta v1.25.0
github.com/fluxcd/pkg/auth v0.36.0
github.com/fluxcd/pkg/cache v0.13.0
github.com/fluxcd/pkg/git v0.42.0
github.com/fluxcd/pkg/masktoken v0.8.0
github.com/fluxcd/pkg/runtime v0.98.0
github.com/fluxcd/pkg/runtime v0.99.0
github.com/fluxcd/pkg/ssa v0.66.0
github.com/fluxcd/pkg/ssh v0.24.0
github.com/getsentry/sentry-go v0.41.0
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ github.com/fluxcd/cli-utils v0.37.1-flux.1 h1:WnG2mHxCPZMj/soIq/S/1zvbrGCJN3GJGb
github.com/fluxcd/cli-utils v0.37.1-flux.1/go.mod h1:aND5wX3LuTFtB7eUT7vsWr8mmxRVSPR2Wkvbn0SqPfw=
github.com/fluxcd/pkg/apis/acl v0.9.0 h1:wBpgsKT+jcyZEcM//OmZr9RiF8klL3ebrDp2u2ThsnA=
github.com/fluxcd/pkg/apis/acl v0.9.0/go.mod h1:TttNS+gocsGLwnvmgVi3/Yscwqrjc17+vhgYfqkfrV4=
github.com/fluxcd/pkg/apis/event v0.23.0 h1:4FsDb/bmukqA2TI6iYI0j4JSH3B+sVTXXsDngrAAgFA=
github.com/fluxcd/pkg/apis/event v0.23.0/go.mod h1:Hoi4DejaNKVahGkRXqGBjT9h1aKmhc7RCYcsgoTieqc=
github.com/fluxcd/pkg/apis/event v0.24.0 h1:WVPf0FrJ5JExRDDGoo4W0jZgHZt0n4E48/e8b3TSmkA=
github.com/fluxcd/pkg/apis/event v0.24.0/go.mod h1:Hoi4DejaNKVahGkRXqGBjT9h1aKmhc7RCYcsgoTieqc=
github.com/fluxcd/pkg/apis/kustomize v1.15.0 h1:p8wPIxdmn0vy0a664rsE9JKCfnliZz4HUsDcTy4ZOxA=
github.com/fluxcd/pkg/apis/kustomize v1.15.0/go.mod h1:XWdsx8P15OiMaQIvmUjYWdmD3zAwhl5q9osl5iCqcOk=
github.com/fluxcd/pkg/apis/meta v1.25.0 h1:fmZgMoe7yITGfhFqdOs7w2GOu3Y/2Vvz4+4p/eay3eA=
Expand All @@ -151,8 +151,8 @@ github.com/fluxcd/pkg/git v0.42.0 h1:ahX9sSaOTd9Fb2I8E61UZx0kSMuP44oxXORSmEzkk8U
github.com/fluxcd/pkg/git v0.42.0/go.mod h1:iqR4eZEhd3gdRSkv+VDP3Qz9WCner3aZ5ClkOUe+3fc=
github.com/fluxcd/pkg/masktoken v0.8.0 h1:Dm5xIVNbg0s6zNttjDvimaG38bKsXwxBVo5b+D7ThVU=
github.com/fluxcd/pkg/masktoken v0.8.0/go.mod h1:Gc73ALOqIe+5Gj2V3JggMNiYcBiZ9bNNDYBE9R5XTTg=
github.com/fluxcd/pkg/runtime v0.98.0 h1:FZB+PUYtvXDrfJRBDcTKdwEHGFarOg5nuDdCUdbb34s=
github.com/fluxcd/pkg/runtime v0.98.0/go.mod h1:L57AzkqndkbnOFgIYStbuwSDPqIBUa+KeevLZ8czl+k=
github.com/fluxcd/pkg/runtime v0.99.0 h1:7UKcpXwdahCtmOxexKJK2BUTzcTLZlemmB5FdQAAJTM=
github.com/fluxcd/pkg/runtime v0.99.0/go.mod h1:MlqGtL3CkfXeTP6Ih5p0R/GdFOWmrxZo3fPpaXYsxN8=
github.com/fluxcd/pkg/ssa v0.66.0 h1:CYbCTuws8Sn1xAaOFNz92yS2iS5YBqJgd+DrzmRxfaQ=
github.com/fluxcd/pkg/ssa v0.66.0/go.mod h1:RjvVjJIoRo1ecsv91yMuiqzO6cpNag80M6MOB/vrJdc=
github.com/fluxcd/pkg/ssh v0.24.0 h1:hrPlxs0hhXf32DRqs68VbsXs0XfQMphyRVIk0rYYJa4=
Expand Down
86 changes: 60 additions & 26 deletions internal/server/event_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ func (s *EventServer) handleEvent() func(w http.ResponseWriter, r *http.Request)
eventLogger.Info("dispatching event", "message", event.Message)

// Dispatch notifications.
var droppedCommitStatusAlerts []*apiv1beta3.Alert
var droppedChangeRequestAlerts []*apiv1beta3.Alert
for i := range alerts {
alert := &alerts[i]
Expand All @@ -90,17 +91,33 @@ func (s *EventServer) handleEvent() func(w http.ResponseWriter, r *http.Request)
"providerName": alert.Spec.ProviderRef.Name,
})
ctx := log.IntoContext(ctx, alertLogger)
droppedChangeRequestProvider, err := s.dispatchNotification(ctx, event, alert)
dropped, err := s.dispatchNotification(ctx, event, alert)
if err != nil {
alertLogger.Error(err, "failed to dispatch notification")
s.Eventf(alert, corev1.EventTypeWarning, "NotificationDispatchFailed",
"failed to dispatch notification for %s: %s", involvedObjectString(event.InvolvedObject), err)
continue
}
if droppedChangeRequestProvider {
if dropped.commitStatus {
droppedCommitStatusAlerts = append(droppedCommitStatusAlerts, alert)
}
if dropped.changeRequest {
droppedChangeRequestAlerts = append(droppedChangeRequestAlerts, alert)
}
}

// Log if any events were dropped due to being related to a commit status provider
// but not having the required commit metadata key.
if len(droppedCommitStatusAlerts) > 0 {
var alertNames []string
for _, alert := range droppedCommitStatusAlerts {
alertNames = append(alertNames, fmt.Sprintf("%s/%s", alert.Namespace, alert.Name))
}
eventLogger.Info(
"event dropped for commit status providers due to missing commit metadata key",
"alerts", alertNames)
}

// Log if any events were dropped due to being related to a change request comment
// provider but not having the required change request metadata key.
if len(droppedChangeRequestAlerts) > 0 {
Expand Down Expand Up @@ -220,16 +237,18 @@ func (s *EventServer) messageIsExcluded(ctx context.Context, msg string, alert *
}

// dispatchNotification constructs and sends notification from the given event
// and alert data. The returned boolean indicates if the event was dropped due
// to being related to a change request provider but not having the required
// change request metadata key.
func (s *EventServer) dispatchNotification(ctx context.Context, event *eventv1.Event, alert *apiv1beta3.Alert) (bool, error) {
params, droppedChangeRequestProvider, err := s.getNotificationParams(ctx, event, alert)
// and alert data. The returned struct indicates if the event was dropped due
// to being related to a provider that requires a specific metadata key but the
// event didn't have that key.
func (s *EventServer) dispatchNotification(ctx context.Context,
event *eventv1.Event, alert *apiv1beta3.Alert) (droppedProviders, error) {

params, dropped, err := s.getNotificationParams(ctx, event, alert)
if err != nil {
return false, err
return droppedProviders{}, err
}
if params == nil {
return droppedChangeRequestProvider, nil
return dropped, nil
}

go func(n notifier.Interface, e eventv1.Event) {
Expand All @@ -249,7 +268,7 @@ func (s *EventServer) dispatchNotification(ctx context.Context, event *eventv1.E
}
}(params.sender, *params.event)

return false, nil
return droppedProviders{}, nil
}

// notificationParams holds the results of the getNotificationParams function.
Expand All @@ -260,52 +279,67 @@ type notificationParams struct {
timeout time.Duration
}

// droppedProviders holds boolean values indicating whether the event was dropped
// due to being related to a provider that requires a specific metadata key but
// the event didn't have that key.
type droppedProviders struct {
commitStatus bool
changeRequest bool
}

// getNotificationParams constructs the notification parameters from the given
// event and alert, and returns a notifier, event, token and timeout for sending
// the notification. The returned event is a mutated form of the input event
// based on the alert configuration. A boolean is also returned to indicate if
// the event was dropped due to being related to a change request provider but
// not having the required change request metadata key.
// based on the alert configuration. A struct indicating if the event was dropped
// due to being related to a provider that requires a specific metadata key but
// the event didn't have that key is also returned.
func (s *EventServer) getNotificationParams(ctx context.Context, event *eventv1.Event,
alert *apiv1beta3.Alert) (*notificationParams, bool, error) {
alert *apiv1beta3.Alert) (*notificationParams, droppedProviders, error) {
// Check if event comes from a different namespace.
if s.noCrossNamespaceRefs && event.InvolvedObject.Namespace != alert.Namespace {
accessDenied := fmt.Errorf(
"alert '%s/%s' can't process event from '%s', cross-namespace references have been blocked",
alert.Namespace, alert.Name, involvedObjectString(event.InvolvedObject))
return nil, false, fmt.Errorf("discarding event, access denied to cross-namespace sources: %w", accessDenied)
return nil, droppedProviders{}, fmt.Errorf("discarding event, access denied to cross-namespace sources: %w", accessDenied)
}

var provider apiv1beta3.Provider
providerName := types.NamespacedName{Namespace: alert.Namespace, Name: alert.Spec.ProviderRef.Name}

err := s.kubeClient.Get(ctx, providerName, &provider)
if err != nil {
return nil, false, fmt.Errorf("failed to read provider: %w", err)
return nil, droppedProviders{}, fmt.Errorf("failed to read provider: %w", err)
}

// Skip if the provider is suspended.
if provider.Spec.Suspend {
return nil, false, nil
return nil, droppedProviders{}, nil
}

// Skip if the event has commit status update metadata but the provider is not a git provider.
// Git providers (github, gitlab, etc.) are the ones that set commit statuses.
if !isCommitStatusProvider(provider.Spec.Type) && isCommitStatusUpdate(event) {
return nil, false, nil
return nil, droppedProviders{}, nil
}

// Skip if the provider is a commit status provider but the event doesn't have the commit metadata key.
if isCommitStatusProvider(provider.Spec.Type) && !hasCommitKey(event) {
// Return true on dropped event for a commit status provider
// when the event doesn't have the commit metadata key.
return nil, droppedProviders{commitStatus: true}, nil
}

// Skip if the provider is a change request comment provider but the event
// Skip if the provider is a change request provider but the event
// doesn't have the change request metadata key.
if isChangeRequestCommentProvider(provider.Spec.Type) && !hasChangeRequestKey(event) {
// Return true on dropped event for a change request comment provider
if isChangeRequestProvider(provider.Spec.Type) && !hasChangeRequestKey(event) {
// Return true on dropped event for a change request provider
// when the event doesn't have the change request metadata key.
return nil, true, nil
return nil, droppedProviders{changeRequest: true}, nil
}

// Check object-level workload identity feature gate.
if provider.Spec.ServiceAccountName != "" && !auth.IsObjectLevelWorkloadIdentityEnabled() {
return nil, false, fmt.Errorf(
return nil, droppedProviders{}, fmt.Errorf(
"to use spec.serviceAccountName for provider authentication please enable the %s feature gate in the controller",
auth.FeatureGateObjectLevelWorkloadIdentity)
}
Expand All @@ -317,20 +351,20 @@ func (s *EventServer) getNotificationParams(ctx context.Context, event *eventv1.
// Create a commit status for the given provider and event, if applicable.
commitStatus, err := createCommitStatus(ctx, &provider, &notification, alert)
if err != nil {
return nil, false, fmt.Errorf("failed to create commit status: %w", err)
return nil, droppedProviders{}, fmt.Errorf("failed to create commit status: %w", err)
}

sender, token, err := createNotifier(ctx, s.kubeClient, &provider, commitStatus, s.tokenCache)
if err != nil {
return nil, false, fmt.Errorf("failed to initialize notifier for provider '%s': %w", provider.Name, err)
return nil, droppedProviders{}, fmt.Errorf("failed to initialize notifier for provider '%s': %w", provider.Name, err)
}

return &notificationParams{
sender: sender,
event: &notification,
token: token,
timeout: provider.GetTimeout(),
}, false, nil
}, droppedProviders{}, nil
}

// createCommitStatus creates a commit status for the given provider and event.
Expand Down
6 changes: 3 additions & 3 deletions internal/server/provider_change_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import (
apiv1beta3 "github.com/fluxcd/notification-controller/api/v1beta3"
)

// isChangeRequestCommentProvider returns true if the provider type is a
// change request comment provider.
func isChangeRequestCommentProvider(providerType string) bool {
// isChangeRequestProvider returns true if the provider type is a
// change request provider.
func isChangeRequestProvider(providerType string) bool {
return providerType == apiv1beta3.GitHubPullRequestCommentProvider ||
providerType == apiv1beta3.GitLabMergeRequestCommentProvider
}
Expand Down
5 changes: 5 additions & 0 deletions internal/server/provider_commit_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,8 @@ func isCommitStatusUpdate(event *eventv1.Event) bool {
key := event.InvolvedObject.GetObjectKind().GroupVersionKind().Group + "/" + eventv1.MetaCommitStatusKey
return event.Metadata[key] == eventv1.MetaCommitStatusUpdateValue
}

// hasCommitKey returns true if the event has the commit metadata key.
func hasCommitKey(event *eventv1.Event) bool {
return event.Metadata[eventv1.Group+"/"+eventv1.MetaCommitKey] != ""
}