@@ -21,6 +21,7 @@ import (
2121 "fmt"
2222 "io/ioutil"
2323 "os"
24+ "strings"
2425
2526 "github.com/go-git/go-git/v5/plumbing/object"
2627 "github.com/go-git/go-git/v5/plumbing/transport"
@@ -29,20 +30,25 @@ import (
2930 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3031 "k8s.io/apimachinery/pkg/runtime"
3132 "k8s.io/apimachinery/pkg/types"
33+ kuberecorder "k8s.io/client-go/tools/record"
34+ "k8s.io/client-go/tools/reference"
3235 ctrl "sigs.k8s.io/controller-runtime"
3336 "sigs.k8s.io/controller-runtime/pkg/client"
3437 "sigs.k8s.io/controller-runtime/pkg/controller"
3538
39+ "github.com/fluxcd/pkg/recorder"
3640 sourcev1 "github.com/fluxcd/source-controller/api/v1alpha1"
3741 intgit "github.com/fluxcd/source-controller/internal/git"
3842)
3943
4044// GitRepositoryReconciler reconciles a GitRepository object
4145type GitRepositoryReconciler struct {
4246 client.Client
43- Log logr.Logger
44- Scheme * runtime.Scheme
45- Storage * Storage
47+ Log logr.Logger
48+ Scheme * runtime.Scheme
49+ Storage * Storage
50+ EventRecorder kuberecorder.EventRecorder
51+ ExternalEventRecorder * recorder.EventRecorder
4652}
4753
4854// +kubebuilder:rbac:groups=source.fluxcd.io,resources=gitrepositories,verbs=get;list;watch;create;update;patch;delete
@@ -51,42 +57,48 @@ type GitRepositoryReconciler struct {
5157func (r * GitRepositoryReconciler ) Reconcile (req ctrl.Request ) (ctrl.Result , error ) {
5258 ctx := context .Background ()
5359
54- var repo sourcev1.GitRepository
55- if err := r .Get (ctx , req .NamespacedName , & repo ); err != nil {
60+ var repository sourcev1.GitRepository
61+ if err := r .Get (ctx , req .NamespacedName , & repository ); err != nil {
5662 return ctrl.Result {}, client .IgnoreNotFound (err )
5763 }
5864
59- log := r .Log .WithValues (repo .Kind , req .NamespacedName )
65+ log := r .Log .WithValues (repository .Kind , req .NamespacedName )
6066
6167 // set initial status
62- if reset , status := r .shouldResetStatus (repo ); reset {
68+ if reset , status := r .shouldResetStatus (repository ); reset {
6369 log .Info ("Initializing Git repository" )
64- repo .Status = status
65- if err := r .Status ().Update (ctx , & repo ); err != nil {
70+ repository .Status = status
71+ if err := r .Status ().Update (ctx , & repository ); err != nil {
6672 log .Error (err , "unable to update GitRepository status" )
6773 return ctrl.Result {Requeue : true }, err
6874 }
6975 } else {
70- repo = sourcev1 .GitRepositoryProgressing (repo )
71- if err := r .Status ().Update (ctx , & repo ); err != nil {
76+ repository = sourcev1 .GitRepositoryProgressing (repository )
77+ if err := r .Status ().Update (ctx , & repository ); err != nil {
7278 log .Error (err , "unable to update GitRepository status" )
7379 return ctrl.Result {Requeue : true }, err
7480 }
7581 }
7682
7783 // try to remove old artifacts
78- if err := r .gc (repo ); err != nil {
84+ if err := r .gc (repository ); err != nil {
7985 log .Error (err , "artifacts GC failed" )
8086 }
8187
8288 // try git sync
83- syncedRepo , err := r .sync (ctx , * repo .DeepCopy ())
89+ syncedRepo , err := r .sync (ctx , * repository .DeepCopy ())
8490 if err != nil {
8591 log .Error (err , "Git repository sync failed" )
92+ r .event (repository , recorder .EventSeverityError , err .Error ())
8693 if err := r .Status ().Update (ctx , & syncedRepo ); err != nil {
8794 log .Error (err , "unable to update GitRepository status" )
8895 }
8996 return ctrl.Result {Requeue : true }, err
97+ } else {
98+ // emit revision change event
99+ if repository .Status .Artifact == nil || syncedRepo .Status .Artifact .Revision != repository .Status .Artifact .Revision {
100+ r .event (syncedRepo , recorder .EventSeverityInfo , sourcev1 .GitRepositoryReadyMessage (syncedRepo ))
101+ }
90102 }
91103
92104 // update status
@@ -98,7 +110,7 @@ func (r *GitRepositoryReconciler) Reconcile(req ctrl.Request) (ctrl.Result, erro
98110 log .Info ("Git repository sync succeeded" , "msg" , sourcev1 .GitRepositoryReadyMessage (syncedRepo ))
99111
100112 // requeue repository
101- return ctrl.Result {RequeueAfter : repo .GetInterval ().Duration }, nil
113+ return ctrl.Result {RequeueAfter : repository .GetInterval ().Duration }, nil
102114}
103115
104116type GitRepositoryReconcilerOptions struct {
@@ -260,3 +272,28 @@ func (r *GitRepositoryReconciler) gc(repository sourcev1.GitRepository) error {
260272 }
261273 return nil
262274}
275+
276+ // emit Kubernetes event and forward event to notification controller if configured
277+ func (r * GitRepositoryReconciler ) event (repository sourcev1.GitRepository , severity , msg string ) {
278+ if r .EventRecorder != nil {
279+ r .EventRecorder .Eventf (& repository , "Normal" , severity , msg )
280+ }
281+ if r .ExternalEventRecorder != nil {
282+ objRef , err := reference .GetReference (r .Scheme , & repository )
283+ if err != nil {
284+ r .Log .WithValues (
285+ strings .ToLower (repository .Kind ),
286+ fmt .Sprintf ("%s/%s" , repository .GetNamespace (), repository .GetName ()),
287+ ).Error (err , "unable to send event" )
288+ return
289+ }
290+
291+ if err := r .ExternalEventRecorder .Eventf (* objRef , nil , severity , severity , msg ); err != nil {
292+ r .Log .WithValues (
293+ strings .ToLower (repository .Kind ),
294+ fmt .Sprintf ("%s/%s" , repository .GetNamespace (), repository .GetName ()),
295+ ).Error (err , "unable to send event" )
296+ return
297+ }
298+ }
299+ }
0 commit comments