|
1 | 1 | # Creating Events
|
2 | 2 |
|
3 |
| -It is often useful to publish *Event* objects from the controller Reconcile function. Events |
4 |
| -allow users to see what is going on with a particular object, and allow automated processes |
5 |
| -to see and respond to them. |
| 3 | +It is often useful to publish *Event* objects from the controller Reconcile function. |
| 4 | + |
| 5 | +Events allow users to see what is going on with a particular object, and allow automated processes to see and respond to them. |
6 | 6 |
|
7 | 7 | {% panel style="success", title="Getting Events" %}
|
8 |
| -Recent Events for an object may be viewed by running `kubectl describe` |
| 8 | +Recent Events for an object can be viewed by running `kubectl describe` |
9 | 9 | {% endpanel %}
|
10 | 10 |
|
11 | 11 | {% method %}
|
12 | 12 |
|
13 | 13 | Events are published from a Controller using an [EventRecorder](https://github.com/kubernetes/client-go/blob/master/tools/record/event.go#L56),
|
14 | 14 | which can be created for a Controller by calling `GetRecorder(name string)` on a Manager.
|
15 | 15 |
|
| 16 | +`Name` should be identifiable and descriptive as it will appear in the `From` column of `kubectl describe` command. |
| 17 | + |
| 18 | +{% sample lang="go" %} |
| 19 | +```go |
| 20 | +// Annotation for generating RBAC role for writing Events |
| 21 | +// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch |
| 22 | +``` |
| 23 | + |
| 24 | +```go |
| 25 | +// ReconcileContainerSet reconciles a ContainerSet object |
| 26 | +type ReconcileContainerSet struct { |
| 27 | + client.Client |
| 28 | + scheme *runtime.Scheme |
| 29 | + recorder record.EventRecorder |
| 30 | +} |
| 31 | +``` |
| 32 | +```go |
| 33 | +// newReconciler returns a new reconcile.Reconciler |
| 34 | +func newReconciler(mgr manager.Manager) reconcile.Reconciler { |
| 35 | + return &ReconcileContainerSet{ |
| 36 | + Client: mgr.GetClient(), |
| 37 | + scheme: mgr.GetScheme(), |
| 38 | + recorder: mgr.GetRecorder("containerset-controller"), |
| 39 | + } |
| 40 | +} |
| 41 | +``` |
| 42 | +{% endmethod %} |
| 43 | + |
| 44 | +{% method %} |
| 45 | + |
| 46 | +## Writing Events |
| 47 | + |
| 48 | +Anatomy of an Event: |
| 49 | + |
16 | 50 | ```go
|
17 | 51 | Event(object runtime.Object, eventtype, reason, message string)
|
18 | 52 | ```
|
19 | 53 |
|
20 | 54 | - `object` is the object this event is about.
|
21 | 55 | - `eventtype` is the type of this event, and is either *Normal* or *Warning*.
|
22 |
| -- `reason` is the reason this event is generated. It should be short and unique with |
23 |
| - `UpperCamelCase` format. The value could appear in *switch* statements by automation. |
| 56 | +- `reason` is the reason this event is generated. It should be short and unique with `UpperCamelCase` format. The value could appear in *switch* statements by automation. |
24 | 57 | - `message` is intended to be consumed by humans.
|
25 | 58 |
|
| 59 | + |
| 60 | +Building on the example introduced in [Controller Example](../basics/simple_controller.md), we can add Events to our reconcile logic using `recorder` as our `EventRecorder` |
| 61 | + |
| 62 | +{% sample lang="go" %} |
| 63 | +```go |
| 64 | + //Reconcile logic up here... |
| 65 | + |
| 66 | + // Create the resource |
| 67 | + found := &appsv1.Deployment{} |
| 68 | + err = r.Get(context.TODO(), types.NamespacedName{Name: deploy.Name, Namespace: deploy.Namespace}, found) |
| 69 | + if err != nil && errors.IsNotFound(err) { |
| 70 | + log.Printf("Creating Deployment %s/%s\n", deploy.Namespace, deploy.Name) |
| 71 | + err = r.Create(context.TODO(), deploy) |
| 72 | + if err != nil { |
| 73 | + return reconcile.Result{}, err |
| 74 | + } |
| 75 | + |
| 76 | + // Write an event to the ContainerSet instance with the namespace and name of the |
| 77 | + // created deployment |
| 78 | + r.recorder.Event(instance, "Normal", "Created", fmt.Sprintf("Created deployment %s/%s", deploy.Namespace, deploy.Name)) |
| 79 | + |
| 80 | + } else if err != nil { |
| 81 | + return reconcile.Result{}, err |
| 82 | + } |
| 83 | + |
| 84 | + // Preform update |
| 85 | + if !reflect.DeepEqual(deploy.Spec, found.Spec) { |
| 86 | + found.Spec = deploy.Spec |
| 87 | + log.Printf("Updating Deployment %s/%s\n", deploy.Namespace, deploy.Name) |
| 88 | + err = r.Update(context.TODO(), found) |
| 89 | + if err != nil { |
| 90 | + return reconcile.Result{}, err |
| 91 | + } |
| 92 | + |
| 93 | + // Write an event to the ContainerSet instance with the namespace and name of the |
| 94 | + // updated deployment |
| 95 | + r.recorder.Event(instance, "Normal", "Updated", fmt.Sprintf("Updated deployment %s/%s", deploy.Namespace, deploy.Name)) |
| 96 | + |
| 97 | + } |
| 98 | + return reconcile.Result{}, nil |
| 99 | +} |
| 100 | +``` |
| 101 | + |
26 | 102 | {% endmethod %}
|
0 commit comments