-
-
Notifications
You must be signed in to change notification settings - Fork 323
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Luca Palmieri
committed
Oct 16, 2021
1 parent
88c5616
commit 1fb72d2
Showing
7 changed files
with
237 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
use crate::event_recorder::EventType; | ||
|
||
/// Required information to publish a new event via [`EventRecorder::publish`]. | ||
/// | ||
/// [`EventRecorder::publish`]: crate::event_recorder::EventRecorder::publish | ||
pub struct NewEvent { | ||
/// The action that was taken (either successfully or unsuccessfully) against | ||
/// the references object. | ||
/// | ||
/// `action` must be machine-readable. | ||
pub action: String, | ||
/// The reason explaining why the `action` was taken. | ||
/// | ||
/// `reason` must be human-readable. | ||
pub reason: String, | ||
/// A optional description of the status of the `action`. | ||
/// | ||
/// `note` must be human-readable. | ||
pub note: Option<String>, | ||
/// The event severity. | ||
pub event_type: EventType, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
use crate::event_recorder::InstanceName; | ||
|
||
/// Details about the event emitter. | ||
/// | ||
/// ```rust | ||
/// use std::convert::TryInto; | ||
/// use kube_runtime::event_recorder::EventSource; | ||
/// | ||
/// let event_source = EventSource { | ||
/// instance_name: "my-awesome-controller-abcdef".try_into().unwrap(), | ||
/// controller_name: "my-awesome-controller".into(), | ||
/// }; | ||
/// ``` | ||
#[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
pub struct EventSource { | ||
/// The name of the controller publishing the event. | ||
/// | ||
/// E.g. `my-awesome-controller`. | ||
pub controller_name: String, | ||
/// The name of the controller instance publishing the event. | ||
/// | ||
/// E.g. `my-awesome-controller-abcdef`. | ||
pub instance_name: InstanceName, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/// The event severity or type. | ||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] | ||
pub enum EventType { | ||
/// An event took place - nothing to worry about. | ||
Normal, | ||
/// Something is not working as expected - it might be worth to have a look. | ||
Warning, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
use std::convert::TryFrom; | ||
|
||
#[derive(Clone, Debug, Eq, PartialEq, Hash)] | ||
/// The name of the controller instance publishing the event. | ||
/// | ||
/// ```rust | ||
/// use std::convert::TryInto; | ||
/// use kube_runtime::event_recorder::InstanceName; | ||
/// | ||
/// let instance_name: InstanceName = "my-awesome-controller-abcdef".try_into().unwrap(); | ||
/// ``` | ||
/// | ||
/// It must be: | ||
/// | ||
/// - shorter than 128 characters. | ||
pub struct InstanceName(String); | ||
|
||
impl TryFrom<&str> for InstanceName { | ||
type Error = String; | ||
|
||
fn try_from(value: &str) -> Result<Self, Self::Error> { | ||
Self::try_from(value.to_string()) | ||
} | ||
} | ||
|
||
impl TryFrom<String> for InstanceName { | ||
type Error = String; | ||
|
||
fn try_from(v: String) -> Result<Self, Self::Error> { | ||
// Limit imposed by Kubernetes' API | ||
let n_chars = v.chars().count(); | ||
if n_chars > 128 { | ||
Err(format!( | ||
"The reporting instance name must be shorter than 128 characters.\n{} is {} characters long.", | ||
v, n_chars | ||
)) | ||
} else { | ||
Ok(Self(v)) | ||
} | ||
} | ||
} | ||
|
||
impl AsRef<str> for InstanceName { | ||
fn as_ref(&self) -> &str { | ||
&self.0 | ||
} | ||
} | ||
|
||
impl Into<String> for InstanceName { | ||
fn into(self) -> String { | ||
self.0 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
pub use event::NewEvent; | ||
pub use event_source::EventSource; | ||
pub use event_type::EventType; | ||
pub use instance_name::InstanceName; | ||
pub use recorder::EventRecorder; | ||
|
||
mod event; | ||
mod event_source; | ||
mod event_type; | ||
mod instance_name; | ||
mod recorder; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
use k8s_openapi::chrono::Utc; | ||
use k8s_openapi::api::core::v1::ObjectReference; | ||
use k8s_openapi::api::events::v1::Event; | ||
use k8s_openapi::apimachinery::pkg::apis::meta::v1::{MicroTime, ObjectMeta}; | ||
use kube::api::PostParams; | ||
use kube::{Api, Client}; | ||
use crate::event_recorder::{EventSource, EventType}; | ||
use crate::event_recorder::event::NewEvent; | ||
|
||
#[derive(Clone)] | ||
/// A publisher abstraction to emit Kubernetes' events. | ||
/// | ||
/// All events emitted by an `EventRecorder` are attached to the [`ObjectReference`] | ||
/// specified when building the recorder using [`EventRecorder::new`]. | ||
/// | ||
/// ```rust | ||
/// use std::convert::TryInto; | ||
/// use kube_runtime::event_recorder::{EventSource, EventRecorder, NewEvent, EventType}; | ||
/// use k8s_openapi::api::core::v1::ObjectReference; | ||
/// | ||
/// # async fn wrapper() -> Result<(), Box<dyn std::error::Error>> { | ||
/// # let k8s_client: kube::Client = todo!(); | ||
/// let event_source = EventSource { | ||
/// instance_name: "my-awesome-controller-abcdef".try_into().unwrap(), | ||
/// controller_name: "my-awesome-controller".into(), | ||
/// }; | ||
/// | ||
/// // You can populate this using `ObjectMeta` and `ApiResource` information | ||
/// // from the object you are working with. | ||
/// let object_reference = ObjectReference { | ||
/// // [...] | ||
/// # ..Default::default() | ||
/// }; | ||
/// | ||
/// let event_recorder = EventRecorder::new(k8s_client, event_source, object_reference); | ||
/// event_recorder.publish(NewEvent { | ||
/// action: "Scheduling".into(), | ||
/// reason: "Pulling".into(), | ||
/// note: Some("Pulling image `nginx`".into()), | ||
/// event_type: EventType::Normal | ||
/// }).await?; | ||
/// # Ok(()) | ||
/// # } | ||
/// ``` | ||
/// | ||
/// Events attached to an object will be shown in the `Events` section of the output of | ||
/// of `kubectl describe` for that object. | ||
pub struct EventRecorder { | ||
event_client: Api<Event>, | ||
event_source: EventSource, | ||
object_reference: ObjectReference, | ||
} | ||
|
||
impl EventRecorder { | ||
/// Build a new [`EventRecorder`] instance to emit events attached to the | ||
/// specified [`ObjectReference`]. | ||
pub fn new( | ||
k8s_client: Client, | ||
event_source: EventSource, | ||
object_reference: ObjectReference, | ||
) -> Self { | ||
let event_client = match object_reference.namespace.as_ref() { | ||
None => Api::all(k8s_client), | ||
Some(namespace) => Api::namespaced(k8s_client, namespace), | ||
}; | ||
Self { | ||
event_client, | ||
event_source, | ||
object_reference, | ||
} | ||
} | ||
|
||
/// Publish a new Kubernetes' event. | ||
/// | ||
/// # Access control | ||
/// | ||
/// The event object is created in the same namespace of the [`ObjectReference`] | ||
/// you specified in [`EventRecorder::new`]. | ||
/// Make sure that your controller has `create` permissions in the required namespaces | ||
/// for the `event` resource in the API group `events.k8s.io`. | ||
pub async fn publish( | ||
&self, | ||
new_event: NewEvent, | ||
) -> Result<(), kube::Error> { | ||
self | ||
.event_client | ||
.create( | ||
&PostParams::default(), | ||
&Event { | ||
action: Some(new_event.action), | ||
reason: Some(new_event.reason), | ||
deprecated_count: None, | ||
deprecated_first_timestamp: None, | ||
deprecated_last_timestamp: None, | ||
deprecated_source: None, | ||
event_time: MicroTime(Utc::now()), | ||
regarding: Some(self.object_reference.clone()), | ||
note: new_event.note, | ||
metadata: ObjectMeta { | ||
namespace: Some(self.object_reference.namespace.clone().unwrap()), | ||
generate_name: Some(format!("{}-", self.event_source.controller_name)), | ||
..Default::default() | ||
}, | ||
reporting_controller: Some(self.event_source.controller_name.clone()), | ||
reporting_instance: Some(self.event_source.instance_name.clone().into()), | ||
series: None, | ||
type_: match new_event.event_type { | ||
EventType::Normal => Some("Normal".into()), | ||
EventType::Warning => Some("Warning".into()), | ||
}, | ||
related: None, | ||
}, | ||
) | ||
.await?; | ||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters