Viewing legacy documentation for Kubebuilder, check out the latest documentation instead.
Creating Events
It is often useful to publish Event objects from the controller Reconcile function.
Events allow users to see what is going on with a particular object, and allow automated processes to see and respond to them.
Getting Events
Recent Events for an object can be viewed by running kubectl describe
Events are published from a Controller using an EventRecorder,
which can be created for a Controller by calling GetRecorder(name string)
on a Manager.
Name
should be identifiable and descriptive as it will appear in the From
column of kubectl describe
command.
// Annotation for generating RBAC role for writing Events
// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch
// ReconcileContainerSet reconciles a ContainerSet object
type ReconcileContainerSet struct {
client.Client
scheme *runtime.Scheme
recorder record.EventRecorder
}
// newReconciler returns a new reconcile.Reconciler
func newReconciler(mgr manager.Manager) reconcile.Reconciler {
return &ReconcileContainerSet{
Client: mgr.GetClient(),
scheme: mgr.GetScheme(),
recorder: mgr.GetRecorder("containerset-controller"),
}
}
Writing Events
Anatomy of an Event:
Event(object runtime.Object, eventtype, reason, message string)
object
is the object this event is about.eventtype
is the type of this event, and is either Normal or Warning.reason
is the reason this event is generated. It should be short and unique withUpperCamelCase
format. The value could appear in switch statements by automation.message
is intended to be consumed by humans.
Building on the example introduced in Controller Example, we can add Events to our reconcile logic using recorder
as our EventRecorder
//Reconcile logic up here...
// Create the resource
found := &appsv1.Deployment{}
err = r.Get(context.TODO(), types.NamespacedName{Name: deploy.Name, Namespace: deploy.Namespace}, found)
if err != nil && errors.IsNotFound(err) {
log.Printf("Creating Deployment %s/%s\n", deploy.Namespace, deploy.Name)
err = r.Create(context.TODO(), deploy)
if err != nil {
return reconcile.Result{}, err
}
// Write an event to the ContainerSet instance with the namespace and name of the
// created deployment
r.recorder.Event(instance, "Normal", "Created", fmt.Sprintf("Created deployment %s/%s", deploy.Namespace, deploy.Name))
} else if err != nil {
return reconcile.Result{}, err
}
// Preform update
if !reflect.DeepEqual(deploy.Spec, found.Spec) {
found.Spec = deploy.Spec
log.Printf("Updating Deployment %s/%s\n", deploy.Namespace, deploy.Name)
err = r.Update(context.TODO(), found)
if err != nil {
return reconcile.Result{}, err
}
// Write an event to the ContainerSet instance with the namespace and name of the
// updated deployment
r.recorder.Event(instance, "Normal", "Updated", fmt.Sprintf("Updated deployment %s/%s", deploy.Namespace, deploy.Name))
}
return reconcile.Result{}, nil
}