/// <summary> /// Attempt to resolve the related resource for the specified event. /// </summary> /// <param name="client">The Kubernetes API client.</param> /// <param name="eventResource">The <see cref="EventV1"/> to process.</param> /// <returns>A task representing the asynchronous operation.</returns> static async Task ResolveRelatedResource(IKubeApiClient client, EventV1 eventResource) { if (client == null) { throw new ArgumentNullException(nameof(client)); } if (eventResource == null) { throw new ArgumentNullException(nameof(eventResource)); } KubeResourceV1 involvedResource = await client.Dynamic().Get(eventResource.InvolvedObject); if (involvedResource != null) { Log.Information("\tResolved related {ResourceModelName} resource for event {EventName}.", involvedResource.GetType().Name, eventResource.Metadata.Name, eventResource.Metadata.Namespace ); } else { Log.Information("\tFailed to resolve related resource for event {EventName}.", eventResource.Metadata.Name, eventResource.Metadata.Namespace ); } }
/// <summary> /// Build a Kubernetes field selector for <see cref="EventV1.InvolvedObject"/> that targets the specified resource. /// </summary> /// <param name="resource">The <see cref="KubeResourceV1"/>.</param> /// <returns>The field selector.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="resource"/> is <c>null</c>. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="resource"/> has <c>null</c> <see cref="KubeResourceV1.Metadata"/>. /// </exception> static string BuildInvolvedObjectFieldSelector(KubeResourceV1 resource) { if (resource == null) { throw new ArgumentNullException(nameof(resource)); } if (resource.Metadata == null) { throw new ArgumentException($"{resource.GetType().Name} has null metadata.", nameof(resource)); } StringBuilder fieldSelector = new StringBuilder() .AppendFormat("involvedObject.kind={0}", resource.Kind) .Append(',') .AppendFormat("involvedObject.apiVersion={0}", resource.ApiVersion) .Append(',') .AppendFormat("involvedObject.name={0}", resource.Metadata.Name); if (!String.IsNullOrWhiteSpace(resource.Metadata.Uid)) { fieldSelector .Append(',') .AppendFormat("involvedObject.uid={0}", resource.Metadata.Uid); } if (!String.IsNullOrWhiteSpace(resource.Metadata.Namespace)) { fieldSelector .Append(',') .AppendFormat("involvedObject.namespace={0}", resource.Metadata.Namespace); } return(fieldSelector.ToString()); }
void OnResourceDeleted(KubeResourceV1 resource) { if (resource == null) { throw new ArgumentNullException(nameof(resource)); } Action <KubeResourceV1> handler; Type resourceType = resource.GetType(); if (!_deleteHandlers.TryGetValue(resourceType, out handler)) { Log.LogWarning("No deletion event handler registered for '{ResourceType}' resources.", resourceType.FullName); return; } try { handler(resource); } catch (Exception handlerError) { Log.LogError(handlerError, "Unexpected error encountered by deletion event handler for '{HandlerType}' resource events.", resourceType.FullName); } }
/// <summary> /// List events that apply to the specified Kubernetes resource. /// </summary> /// <param name="eventClient">The Kubernetes API client.</param> /// <param name="resource">The <see cref="KubeResourceV1"/>.</param> /// <param name="onlyNewEvents">Only return events newer than the <paramref name="resource"/>'s ResourceVersion?</param> /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> that can be used to cancel the request.</param> /// <returns>An <see cref="EventListV1"/> containing the relevant events.</returns> public static Task <EventListV1> List(this IEventClientV1 eventClient, KubeResourceV1 resource, bool onlyNewEvents = false, CancellationToken cancellationToken = default) { if (eventClient == null) { throw new ArgumentNullException(nameof(eventClient)); } if (resource == null) { throw new ArgumentNullException(nameof(resource)); } string fieldSelector = BuildInvolvedObjectFieldSelector(resource); return(eventClient.List( fieldSelector: fieldSelector, resourceVersion: onlyNewEvents ? resource.Metadata.ResourceVersion : null, cancellationToken: cancellationToken )); }
/// <summary> /// Determines if a Kubernetes resource has a specific annotation with a value matching one of a set of <paramref name="expectedValues"/>. /// </summary> public static bool HasAnnotation(this KubeResourceV1 resource, string key, ISet <string> expectedValues) => resource.TryGetAnnotation(key, out string value) && expectedValues.Contains(value);
/// <summary> /// Determines if a Kubernetes resource has a specific annotation with a specific value. /// </summary> public static bool HasAnnotation(this KubeResourceV1 resource, string key, string expectedValue) => resource.TryGetAnnotation(key, out string value) && value == expectedValue;
/// <summary> /// Gets a Kubernetes annotation from the resource if present. /// </summary> public static bool TryGetAnnotation(this KubeResourceV1 resource, string key, out string value) => resource.Metadata.Annotations.TryGetValue(key, out value);
/// <summary> /// Gets a Kubernetes annotation from the resource or an empty string. /// </summary> public static string GetAnnotationOrStringEmpty(this KubeResourceV1 resource, string key) => resource.Metadata.Annotations.TryGetValue(key, out string value) ? value : string.Empty;
/// <summary> /// Determines if a Kubernetes resource has a specific label with a value matching one of a set of <paramref name="expectedValues"/>. /// </summary> public static bool HasLabel(this KubeResourceV1 resource, string labelName, ISet <string> expectedValues) => resource.TryGetLabel(labelName, out string value) && expectedValues.Contains(value);
/// <summary> /// Determines if a Kubernetes resource has a specific label with a specific value. /// </summary> public static bool HasLabel(this KubeResourceV1 resource, string labelName, string expectedValue) => resource.TryGetLabel(labelName, out string value) && value == expectedValue;
/// <summary> /// Gets a Kubernetes labels from the resource if present. /// </summary> public static bool TryGetLabel(this KubeResourceV1 resource, string labelName, out string value) => resource.Metadata.Labels.TryGetValue(labelName, out value);
/// <summary> /// Returns <c>true</c> if the name and namespace of the other resource equal those of this resource. /// </summary> /// <param name="other"></param> /// <returns></returns> public bool NameEquals(KubeResourceV1 other) => Metadata.Name == other.Metadata.Name && (Metadata.Namespace ?? "") == (other.Metadata.Namespace ?? "");
/// <summary> /// Watch for events that apply to the specified Kubernetes resource. /// </summary> /// <param name="eventClient">The Kubernetes API client.</param> /// <param name="resource">The <see cref="KubeResourceV1"/>.</param> /// <returns>An <see cref="EventListV1"/> containing the relevant events.</returns> public static IObservable <IResourceEventV1 <EventV1> > WatchAll(this IEventClientV1 eventClient, KubeResourceV1 resource) { if (eventClient == null) { throw new ArgumentNullException(nameof(eventClient)); } if (resource == null) { throw new ArgumentNullException(nameof(resource)); } string fieldSelector = BuildInvolvedObjectFieldSelector(resource); return(eventClient.WatchAll( fieldSelector: fieldSelector, resourceVersion: resource.Metadata.ResourceVersion )); }