Skip to content

Commit

Permalink
move to event pkg and add test
Browse files Browse the repository at this point in the history
  • Loading branch information
hanxiaop committed Oct 22, 2024
1 parent 77f0264 commit 26d214f
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 109 deletions.
101 changes: 0 additions & 101 deletions internal/api/event.go

This file was deleted.

3 changes: 2 additions & 1 deletion internal/api/promote_to_stage_v1alpha1.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
kargoapi "github.com/akuity/kargo/api/v1alpha1"
"github.com/akuity/kargo/internal/api/user"
"github.com/akuity/kargo/internal/kargo"
libEvent "github.com/akuity/kargo/internal/kubernetes/event"
svcv1alpha1 "github.com/akuity/kargo/pkg/api/service/v1alpha1"
)

Expand Down Expand Up @@ -138,7 +139,7 @@ func (s *server) recordPromotionCreatedEvent(

s.recorder.AnnotatedEventf(
p,
NewPromotionEventAnnotations(ctx, actor, p, f),
libEvent.NewPromotionEventAnnotations(ctx, actor, p, f),
corev1.EventTypeNormal,
kargoapi.EventReasonPromotionCreated,
msg,
Expand Down
5 changes: 2 additions & 3 deletions internal/controller/promotions/promotions.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/source"

kargoapi "github.com/akuity/kargo/api/v1alpha1"
"github.com/akuity/kargo/internal/api"
"github.com/akuity/kargo/internal/controller"
argocd "github.com/akuity/kargo/internal/controller/argocd/api/v1alpha1"
"github.com/akuity/kargo/internal/directives"
Expand Down Expand Up @@ -394,7 +393,7 @@ func (r *reconciler) Reconcile(
msg += fmt.Sprintf(": %s", newStatus.Message)
}

eventAnnotations := api.NewPromotionEventAnnotations(ctx,
eventAnnotations := libEvent.NewPromotionEventAnnotations(ctx,
kargoapi.FormatEventControllerActor(r.cfg.Name()),
promo, freight)

Expand Down Expand Up @@ -622,7 +621,7 @@ func (r *reconciler) terminatePromotion(
return err
}

eventMeta := api.NewPromotionEventAnnotations(ctx, "", promo, freight)
eventMeta := libEvent.NewPromotionEventAnnotations(ctx, "", promo, freight)
eventMeta[kargoapi.AnnotationKeyEventActor] = actor

r.recorder.AnnotatedEventf(
Expand Down
3 changes: 1 addition & 2 deletions internal/controller/stages/stages.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/source"

kargoapi "github.com/akuity/kargo/api/v1alpha1"
"github.com/akuity/kargo/internal/api"
"github.com/akuity/kargo/internal/controller"
argocd "github.com/akuity/kargo/internal/controller/argocd/api/v1alpha1"
rollouts "github.com/akuity/kargo/internal/controller/rollouts/api/v1alpha1"
Expand Down Expand Up @@ -983,7 +982,7 @@ func (r *reconciler) syncNormalStage(

r.recorder.AnnotatedEventf(
&promo,
api.NewPromotionEventAnnotations(
libEvent.NewPromotionEventAnnotations(
ctx,
kargoapi.FormatEventControllerActor(r.cfg.Name()),
&promo,
Expand Down
94 changes: 94 additions & 0 deletions internal/kubernetes/event/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package event

import (
"context"
"encoding/json"
"errors"
"time"

corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
Expand All @@ -13,6 +15,8 @@ import (
"k8s.io/client-go/util/retry"
libClient "sigs.k8s.io/controller-runtime/pkg/client"

kargoapi "github.com/akuity/kargo/api/v1alpha1"
"github.com/akuity/kargo/internal/directives"
"github.com/akuity/kargo/internal/logging"
)

Expand Down Expand Up @@ -140,3 +144,93 @@ func (e *sink) Patch(event *corev1.Event, data []byte) (*corev1.Event, error) {
err := e.client.Patch(e.ctx, event, libClient.RawPatch(types.StrategicMergePatchType, data))
return event, err
}

type AppReference struct {
Name string `json:"name"`
Namespace string `json:"namespace,omitempty"`
}

// NewPromotionEventAnnotations returns annotations for a Promotion related event.
// It may skip some fields when error occurred during serialization, to record event with best-effort.
func NewPromotionEventAnnotations(
ctx context.Context,
actor string,
p *kargoapi.Promotion,
f *kargoapi.Freight,
) map[string]string {
logger := logging.LoggerFromContext(ctx)

annotations := map[string]string{
kargoapi.AnnotationKeyEventProject: p.GetNamespace(),
kargoapi.AnnotationKeyEventPromotionName: p.GetName(),
kargoapi.AnnotationKeyEventFreightName: p.Spec.Freight,
kargoapi.AnnotationKeyEventStageName: p.Spec.Stage,
kargoapi.AnnotationKeyEventPromotionCreateTime: p.GetCreationTimestamp().Format(time.RFC3339),
}

if actor != "" {
annotations[kargoapi.AnnotationKeyEventActor] = actor
}
// All Promotion-related events are emitted after the promotion was created.
// Therefore, if the promotion knows who triggered it, set them as an actor.
if promoteActor, ok := p.Annotations[kargoapi.AnnotationKeyCreateActor]; ok {
annotations[kargoapi.AnnotationKeyEventActor] = promoteActor
}

if f != nil {
annotations[kargoapi.AnnotationKeyEventFreightCreateTime] = f.CreationTimestamp.Format(time.RFC3339)
annotations[kargoapi.AnnotationKeyEventFreightAlias] = f.Alias
if len(f.Commits) > 0 {
data, err := json.Marshal(f.Commits)
if err != nil {
logger.Error(err, "marshal freight commits in JSON")

Check warning on line 186 in internal/kubernetes/event/event.go

View check run for this annotation

Codecov / codecov/patch

internal/kubernetes/event/event.go#L186

Added line #L186 was not covered by tests
} else {
annotations[kargoapi.AnnotationKeyEventFreightCommits] = string(data)
}
}
if len(f.Images) > 0 {
data, err := json.Marshal(f.Images)
if err != nil {
logger.Error(err, "marshal freight images in JSON")

Check warning on line 194 in internal/kubernetes/event/event.go

View check run for this annotation

Codecov / codecov/patch

internal/kubernetes/event/event.go#L194

Added line #L194 was not covered by tests
} else {
annotations[kargoapi.AnnotationKeyEventFreightImages] = string(data)
}
}
if len(f.Charts) > 0 {
data, err := json.Marshal(f.Charts)
if err != nil {
logger.Error(err, "marshal freight charts in JSON")

Check warning on line 202 in internal/kubernetes/event/event.go

View check run for this annotation

Codecov / codecov/patch

internal/kubernetes/event/event.go#L202

Added line #L202 was not covered by tests
} else {
annotations[kargoapi.AnnotationKeyEventFreightCharts] = string(data)
}
}
}

var apps []AppReference
for _, step := range p.Spec.Steps {
if step.Uses != "argocd-update" || step.Config == nil {
continue

Check warning on line 212 in internal/kubernetes/event/event.go

View check run for this annotation

Codecov / codecov/patch

internal/kubernetes/event/event.go#L212

Added line #L212 was not covered by tests
}
var cfg directives.ArgoCDUpdateConfig
if err := json.Unmarshal(step.Config.Raw, &cfg); err != nil {
logger.Error(err, "unmarshal ArgoCD update config")
continue

Check warning on line 217 in internal/kubernetes/event/event.go

View check run for this annotation

Codecov / codecov/patch

internal/kubernetes/event/event.go#L216-L217

Added lines #L216 - L217 were not covered by tests
}
for _, app := range cfg.Apps {
apps = append(apps, AppReference{
Name: app.Name,
Namespace: app.Namespace,
})
}
}
if len(apps) > 0 {
data, err := json.Marshal(apps)
if err != nil {
logger.Error(err, "marshal ArgoCD apps in JSON")

Check warning on line 229 in internal/kubernetes/event/event.go

View check run for this annotation

Codecov / codecov/patch

internal/kubernetes/event/event.go#L229

Added line #L229 was not covered by tests
} else {
annotations[kargoapi.AnnotationKeyEventApplications] = string(data)
}
}

return annotations
}
86 changes: 86 additions & 0 deletions internal/kubernetes/event/event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ import (
"errors"
"net/http"
"testing"
"time"

"github.com/go-logr/logr"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/client/fake"

"github.com/akuity/kargo/api/v1alpha1"
"github.com/akuity/kargo/internal/logging"
)

Expand Down Expand Up @@ -81,3 +84,86 @@ func Test_newSink(t *testing.T) {
require.NotNil(t, s.client)
require.NotNil(t, s.ctx)
}

func TestNewPromotionEventAnnotations(t *testing.T) {
testCases := map[string]struct {
actor string
promotion *v1alpha1.Promotion
freight *v1alpha1.Freight
expected map[string]string
}{
"promotion with freight and argocd apps": {
actor: "test-user",
promotion: &v1alpha1.Promotion{
ObjectMeta: metav1.ObjectMeta{
Name: "test-promotion",
Namespace: "test-namespace",
CreationTimestamp: metav1.Time{
Time: time.Date(2024, 10, 22, 0, 0, 0, 0, time.UTC),
},
Annotations: map[string]string{
v1alpha1.AnnotationKeyCreateActor: "promotion-creator",
},
},
Spec: v1alpha1.PromotionSpec{
Freight: "test-freight",
Stage: "test-stage",
Steps: []v1alpha1.PromotionStep{
{
Uses: "argocd-update",
Config: &v1.JSON{Raw: []byte(`{
"apps": [
{
"name": "test-app-1"
},
{
"name": "test-app-2",
"namespace": "test-namespace"
}
]
}`)},
},
},
},
},
freight: &v1alpha1.Freight{
ObjectMeta: metav1.ObjectMeta{
CreationTimestamp: metav1.Time{
Time: time.Date(2024, 10, 22, 0, 0, 0, 0, time.UTC),
},
},
Alias: "test-alias",
Commits: []v1alpha1.GitCommit{{Tag: "test-tag"}},
Images: []v1alpha1.Image{{Tag: "test-tag"}},
Charts: []v1alpha1.Chart{{Name: "test-chart"}},
},
expected: map[string]string{
v1alpha1.AnnotationKeyEventProject: "test-namespace",
v1alpha1.AnnotationKeyEventPromotionName: "test-promotion",
v1alpha1.AnnotationKeyEventFreightName: "test-freight",
v1alpha1.AnnotationKeyEventStageName: "test-stage",
v1alpha1.AnnotationKeyEventPromotionCreateTime: "2024-10-22T00:00:00Z",
v1alpha1.AnnotationKeyEventActor: "promotion-creator",
v1alpha1.AnnotationKeyEventFreightCreateTime: "2024-10-22T00:00:00Z",
v1alpha1.AnnotationKeyEventFreightAlias: "test-alias",
v1alpha1.AnnotationKeyEventFreightCommits: `[{"tag":"test-tag"}]`,
v1alpha1.AnnotationKeyEventFreightImages: `[{"tag":"test-tag"}]`,
v1alpha1.AnnotationKeyEventFreightCharts: `[{"name":"test-chart"}]`,
v1alpha1.AnnotationKeyEventApplications: `[{"name":"test-app-1"},{"name":"test-app-2","namespace":"test-namespace"}]`,

Check failure on line 152 in internal/kubernetes/event/event_test.go

View workflow job for this annotation

GitHub Actions / lint-go

the line is 133 characters long, which exceeds the maximum of 120 characters. (lll)
},
},
}

for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
result := NewPromotionEventAnnotations(context.TODO(), tc.actor, tc.promotion, tc.freight)

require.Equal(t, len(tc.expected), len(result), "Number of annotations doesn't match")
for key, expectedValue := range tc.expected {
actualValue, exists := result[key]
require.True(t, exists, "Expected annotation %s not found", key)
require.Equal(t, expectedValue, actualValue, "Annotation %s value mismatch", key)
}
})
}
}
3 changes: 1 addition & 2 deletions internal/webhook/promotion/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"

kargoapi "github.com/akuity/kargo/api/v1alpha1"
"github.com/akuity/kargo/internal/api"
libEvent "github.com/akuity/kargo/internal/kubernetes/event"
"github.com/akuity/kargo/internal/logging"
libWebhook "github.com/akuity/kargo/internal/webhook"
Expand Down Expand Up @@ -373,7 +372,7 @@ func (w *webhook) recordPromotionCreatedEvent(
actor := kargoapi.FormatEventKubernetesUserActor(req.UserInfo)
w.recorder.AnnotatedEventf(
p,
api.NewPromotionEventAnnotations(ctx, actor, p, f),
libEvent.NewPromotionEventAnnotations(ctx, actor, p, f),
corev1.EventTypeNormal,
kargoapi.EventReasonPromotionCreated,
"Promotion created for Stage %q by %q",
Expand Down

0 comments on commit 26d214f

Please sign in to comment.