예제 #1
0
        public void Record(string action, string reason, string message, V1ObjectReference objRef)
        {
            var occurrence = DateTime.Now;
            var key        = new EventKey($"{objRef.ApiVersion}/{objRef.Kind}", action, reason, message, $"{objRef.NamespaceProperty}/{objRef.Name}");

            if (!events.ContainsKey(key))
            {
                Logger.LogDebug("Initializing new EventDetail entry for {objName}", key.ToString());
                events.Add(key, EventDetails.Initialize(objRef.Name, occurrence));
            }

            EventDetails details = events[key];

            details.AddOccurrence(occurrence);

            Logger.LogDebug("Writing event to Kubernetes ({key}, Count: {count}", key.ToString(), details.Count);
            V1Event ev = new V1Event(objRef,
                                     new V1ObjectMeta()
            {
                Name = details.Name
            },
                                     action: action,
                                     message: message,
                                     reason: reason,
                                     firstTimestamp: details.FirstSeen,
                                     lastTimestamp: details.LastSeen,
                                     count: details.Count);

            Kubernetes.ReplaceNamespacedEventAsync(ev, details.Name, objRef.NamespaceProperty);
        }
예제 #2
0
 private async Task<string> DescribeObject(Kubernetes client, V1Namespace ns, V1Event o, StringBuilder buffer)
 {
     var fetched = await client.ReadNamespacedEventAsync(o.Metadata.Name, ns.Metadata.Name).ConfigureAwait(false);
     buffer.AppendLine($"API Veresion: {fetched.ApiVersion}");
     buffer.AppendLine($"Kind: {fetched.Kind}");
     buffer.AppendLine(DescribeMetadata(fetched.Metadata));
     return $"Event - {fetched.Metadata.Name}";
 }
 /// <summary>
 /// Gets the matching <see cref="V1EventFilter"/> for the specified <see cref="V1Event"/>
 /// </summary>
 /// <param name="e">The <see cref="V1Event"/> to get the matching <see cref="V1EventFilter"/> for</param>
 /// <returns>The matching <see cref="V1EventFilter"/> for the specified <see cref="V1Event"/>, if any</returns>
 public virtual V1EventFilter?GetMatchingFilterFor(V1Event e)
 {
     if (e == null)
     {
         throw new ArgumentNullException(nameof(e));
     }
     return(this.Filters.FirstOrDefault(f => f.Filters(e)));
 }
 /// <summary>
 /// Determines whether or not the <see cref="V1CorrelationCondition"/> matches the specified <see cref="V1Event"/>
 /// </summary>
 /// <param name="e">The <see cref="V1Event"/> to match</param>
 /// <returns>A boolean indicating whether or not the <see cref="V1CorrelationCondition"/> matches the specified <see cref="V1Event"/></returns>
 public virtual bool Matches(V1Event e)
 {
     if (e == null)
     {
         throw new ArgumentNullException(nameof(e));
     }
     return(this.GetMatchingFilterFor(e) != null);
 }
예제 #5
0
 /// <summary>
 /// Gets the first matching <see cref="V1CorrelationCondition"/> for the specified <see cref="V1Event"/>
 /// </summary>
 /// <param name="e">The <see cref="V1Event"/> to get the <see cref="V1CorrelationCondition"/> for</param>
 /// <returns>The first matching <see cref="V1CorrelationCondition"/> for the specified <see cref="V1Event"/>, if any</returns>
 public virtual V1CorrelationCondition?GetMatchingConditionFor(V1Event e)
 {
     if (e == null)
     {
         throw new ArgumentNullException(nameof(e));
     }
     return(this.Conditions.FirstOrDefault(c => c.Matches(e)));
 }
예제 #6
0
 /// <summary>
 /// Determines whether or not the specified <see cref="V1Event"/> matches one of the <see cref="V1Correlation"/>'s conditions
 /// </summary>
 /// <param name="e">The <see cref="V1Event"/> to check</param>
 /// <returns>A boolean indicating whether or not the specified <see cref="V1Event"/> matches one of the <see cref="V1Correlation"/>'s conditions</returns>
 public virtual bool AppliesTo(V1Event e)
 {
     if (e == null)
     {
         throw new ArgumentNullException(nameof(e));
     }
     return(this.GetMatchingConditionFor(e) != null);
 }
예제 #7
0
        public void EmitEvent(string action, string reason, string message, CustomResource involvedObject)
        {
            var     objRef = new V1ObjectReference(involvedObject.ApiVersion, kind: involvedObject.Kind, name: involvedObject.Metadata.Name, namespaceProperty: involvedObject.Metadata.NamespaceProperty);
            V1Event ev     = new V1Event(objRef, new V1ObjectMeta()
            {
                GenerateName = involvedObject.Metadata.Name
            }, action: action, message: message, reason: reason, firstTimestamp: DateTime.Now);

            client.CreateNamespacedEvent(ev, involvedObject.Metadata.NamespaceProperty);
        }
예제 #8
0
 /// <inheritdoc/>
 public virtual async Task <bool> TryCorrelateAsync(V1Event e, IEnumerable <string> mappingKeys, CancellationToken cancellationToken = default)
 {
     if (e == null)
     {
         throw new ArgumentNullException(nameof(e));
     }
     if (mappingKeys == null)
     {
         mappingKeys = Array.Empty <string>();
     }
     return(await this.SynapseRuntimeApi.TryCorrelateAsync(new() { WorkflowInstanceId = this.Instance.Id, Event = e, MappingKeys = mappingKeys }, cancellationToken));
 }
예제 #9
0
        /// <summary>
        ///     Generates a Cloud Event for a Kubernetes Event (v1 schema)
        /// </summary>
        /// <param name="kubernetesEvent">Event that occured in Kubernetes cluster</param>
        public CloudEvent GenerateFromKubernetesEvent(V1Event kubernetesEvent)
        {
            Guard.NotNull(kubernetesEvent, nameof(kubernetesEvent));

            var eventId   = kubernetesEvent.Metadata.Uid ?? Guid.NewGuid().ToString();
            var eventTime = kubernetesEvent.LastTimestamp ?? DateTime.UtcNow;

            var cloudEvent = new CloudEvent(CloudEventsSpecVersion.V0_1, DefaultEventType, EventSource, eventId, eventTime)
            {
                ContentType = new ContentType(contentType: "application/json"),
                Data        = kubernetesEvent
            };

            return(cloudEvent);
        }
 /// <summary>
 /// Ingests the specified <see cref="CloudEvent"/>
 /// </summary>
 /// <param name="serviceProvider">The current <see cref="IServiceProvider"/></param>
 /// <param name="e">The <see cref="CloudEvent"/> to ingest</param>
 /// <param name="cancellationToken">A <see cref="CancellationToken"/></param>
 /// <returns>A new awaitable <see cref="Task"/></returns>
 protected virtual async Task CorrelateAsync(IServiceProvider serviceProvider, CloudEvent e, CancellationToken cancellationToken)
 {
     try
     {
         var mediator = serviceProvider.GetRequiredService <IMediator>();
         await mediator.ExecuteAndUnwrapAsync(new V1CorrelateEventCommand(V1Event.CreateFrom(e)), cancellationToken);
     }
     catch (TaskCanceledException)
     {
         throw;
     }
     catch (Exception ex)
     {
         this.Logger.LogError("An error occured while processing an incoming cloud event: {ex}", ex.ToString());
     }
 }
        /// <summary>
        /// Handles an incoming <see cref="CloudEvent"/>
        /// </summary>
        /// <param name="e">The <see cref="CloudEvent"/> to handle</param>
        /// <param name="cancellationToken">A <see cref="CancellationToken"/></param>
        /// <returns>A new awaitable <see cref="Task"/></returns>
        protected virtual async Task OnEventAsync(CloudEvent e)
        {
            using (await this.Lock.LockAsync(this.CancellationTokenSource.Token))
            {
                if (this.IdleTimer != null)
                {
                    this.IdleTimer.Dispose();
                    this.IdleTimer = null !;
                }
                if ((!string.IsNullOrWhiteSpace(this.EventDefinition.Source) && !Regex.IsMatch(e.Source !.ToString(), this.EventDefinition.Source, RegexOptions.IgnoreCase)) ||
                    (!string.IsNullOrWhiteSpace(this.EventDefinition.Type) && !Regex.IsMatch(e.Type !, this.EventDefinition.Type, RegexOptions.IgnoreCase)))
                {
                    return;
                }
                if (!await this.Context.Workflow.TryCorrelateAsync(V1Event.CreateFrom(e), this.EventDefinition.Correlations?.Select(c => c.ContextAttributeName) !, this.CancellationTokenSource.Token))
                {
                    return;
                }
                await this.OnNextAsync(new V1WorkflowActivityCompletedIntegrationEvent(this.Activity.Id, e.Data), this.CancellationTokenSource.Token);

                await this.OnCompletedAsync(this.CancellationTokenSource.Token);
            }
        }
예제 #12
0
        private async Task Update()
        {
            Item = await State.Client.ReadNamespacedEventAsync(Name, Namespace);

            StateHasChanged();
        }
 private async Task HandleKubernetesEvent(WatchEventType type, V1Event kubernetesEvent)
 {
     var cloudEvent = _cloudEventsSchematizer.GenerateFromKubernetesEvent(kubernetesEvent);
     await _cloudEventsPublisher.Publish(cloudEvent);
 }
 /// <summary>
 /// Initializes a new <see cref="V1GetEventCorrelationsQuery"/>
 /// </summary>
 /// <param name="e">The <see cref="V1Event"/> to get the matching <see cref="V1Correlation"/>s for</param>
 public V1GetEventCorrelationsQuery(V1Event e)
 {
     this.Event = e;
 }
예제 #15
0
        /// <summary>
        /// Performs a correlation on a <see cref="V1Event"/>, in a given <see cref="V1CorrelationContext"/> and using the specified <see cref="V1EventFilter"/>
        /// </summary>
        /// <param name="correlation">The <see cref="V1Correlation"/> to perform</param>
        /// <param name="correlationContext">The <see cref="V1CorrelationContext"/> in which to perform the <see cref="V1Correlation"/></param>
        /// <param name="e">The <see cref="V1Event"/> to correlate</param>
        /// <param name="filter">The <see cref="V1EventFilter"/> used to correlate the <see cref="V1Event"/></param>
        /// <param name="cancellationToken">A <see cref="CancellationToken"/></param>
        /// <returns>A new awaitable <see cref="Task"/></returns>
        protected virtual async Task CorrelateAsync(V1Correlation correlation, V1CorrelationContext correlationContext, V1Event e, V1EventFilter filter, CancellationToken cancellationToken = default)
        {
            this.Logger.LogInformation("Correlating event to context with id '{contextId}'...", correlationContext.Id);
            correlationContext.Correlate(e, filter.CorrelationMappings.Keys, true);
            correlation = await this.Correlations.UpdateAsync(correlation, cancellationToken);

            await this.Correlations.SaveChangesAsync(cancellationToken);

            this.Logger.LogInformation("Event successfully correlated to context with id '{contextId}'", correlationContext.Id);
            this.Logger.LogInformation("Attempting to complete the correlation with id '{correlationId}' in context with id '{contextId}'...", correlation.Id, correlationContext.Id);
            if (!correlation.TryComplete(correlationContext))
            {
                this.Logger.LogInformation("Correlations conditions are not met in the specified correlation context");
                return;
            }
            this.Logger.LogInformation("Correlation with id '{correlationId}' has been completed in context with id '{contextId}. Computing outcome...", correlation.Id, correlationContext.Id);
            switch (correlation.Outcome.Type)
            {
            case V1CorrelationOutcomeType.Start:
                await this.Mediator.ExecuteAndUnwrapAsync(new V1CreateWorkflowInstanceCommand(correlation.Outcome.Target, V1WorkflowInstanceActivationType.Trigger, new(), correlationContext, true, null), cancellationToken);

                break;

            case V1CorrelationOutcomeType.Correlate:
                await this.Mediator.ExecuteAndUnwrapAsync(new V1CorrelateWorkflowInstanceCommand(correlation.Outcome.Target, correlationContext), cancellationToken);

                break;

            default:
                throw new NotSupportedException($"The specified {nameof(V1CorrelationOutcomeType)} '{correlation.Outcome.Type}' is not supported");
            }
            correlation.ReleaseContext(correlationContext);
            correlation = await this.Correlations.UpdateAsync(correlation, cancellationToken);

            await this.Correlations.SaveChangesAsync(cancellationToken);

            if (correlation.Lifetime == V1CorrelationLifetime.Singleton)
            {
                this.Logger.LogInformation("The correlation with id '{correlationId}' is a singleton and its context has been released. Disposing of it...", correlation.Id);
                await this.Mediator.ExecuteAndUnwrapAsync(new V1DeleteCorrelationCommand(correlation.Id), cancellationToken);

                this.Logger.LogInformation("The correlation with id '{correlationId}' has been successfully disposed of", correlation.Id);
            }
            this.Logger.LogInformation("Correlation outcome successfully computed");
        }
예제 #16
0
 /// <summary>
 /// Initializes a new <see cref="V1CorrelateEventCommand"/>
 /// </summary>
 /// <param name="e">The <see cref="V1Event"/> to correlate</param>
 public V1CorrelateEventCommand(V1Event e)
 {
     this.Event = e;
 }
 /// <summary>
 /// Initializes a new <see cref="V1TryCorrelateWorkflowInstanceCommand"/>
 /// </summary>
 /// <param name="workflowInstanceId">The id of the <see cref="V1WorkflowInstance"/> to correlate</param>
 /// <param name="e">The <see cref="V1Event"/> to correlate</param>
 /// <param name="mappingKeys">An <see cref="IEnumerable{T}"/> containing the mapping keys to use to correlate the <see cref="V1WorkflowInstance"/></param>
 public V1TryCorrelateWorkflowInstanceCommand(string workflowInstanceId, V1Event e, IEnumerable <string> mappingKeys)
 {
     this.WorkflowInstanceId = workflowInstanceId;
     this.Event       = e;
     this.MappingKeys = mappingKeys;
 }