Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Cloudwatch Events #16

Closed
adamhathcock opened this issue Dec 15, 2016 · 6 comments
Closed

Support Cloudwatch Events #16

adamhathcock opened this issue Dec 15, 2016 · 6 comments
Labels
feature-request A feature should be added or improved.

Comments

@adamhathcock
Copy link

I'd like to officially support events like described here: https://aws.amazon.com/blogs/compute/monitor-cluster-state-with-amazon-ecs-event-stream/

{
  "version": "0",
  "id": "8f07966c-b005-4a0f-9ee9-63d2c41448b3",
  "detail-type": "ECS Task State Change",
  "source": "aws.ecs",
  "account": "244698725403",
  "time": "2016-10-17T20:29:14Z",
  "region": "us-east-1",
  "resources": [
    "arn:aws:ecs:us-east-1:123456789012:task/cdf83842-a918-482b-908b-857e667ce328"
  ],
  "detail": {
    "clusterArn": "arn:aws:ecs:us-east-1:123456789012:cluster/eventStreamTestCluster",
    "containerInstanceArn": "arn:aws:ecs:us-east-1:123456789012:container-instance/f813de39-e42c-4a27-be3c-f32ebb79a5dd",
    "containers": [
      {
        "containerArn": "arn:aws:ecs:us-east-1:123456789012:container/4b5f2b75-7d74-4625-8dc8-f14230a6ae7e",
        "exitCode": 1,
        "lastStatus": "STOPPED",
        "name": "web",
        "networkBindings": [
          {
            "bindIP": "0.0.0.0",
            "containerPort": 80,
            "hostPort": 80,
            "protocol": "tcp"
          }
        ],
        "taskArn": "arn:aws:ecs:us-east-1:123456789012:task/cdf83842-a918-482b-908b-857e667ce328"
      }
    ],
    "createdAt": "2016-10-17T20:28:53.671Z",
    "desiredStatus": "STOPPED",
    "lastStatus": "STOPPED",
    "overrides": {
      "containerOverrides": [
        {
          "name": "web"
        }
      ]
    },
    "startedAt": "2016-10-17T20:29:14.179Z",
    "stoppedAt": "2016-10-17T20:29:14.332Z",
    "stoppedReason": "Essential container in task exited",
    "updatedAt": "2016-10-17T20:29:14.332Z",
    "taskArn": "arn:aws:ecs:us-east-1:123456789012:task/cdf83842-a918-482b-908b-857e667ce328",
    "taskDefinitionArn": "arn:aws:ecs:us-east-1:123456789012:task-definition/wpunconfiguredfail:1",
    "version": 3
  }
}
@jkpindahbc
Copy link

jkpindahbc commented May 23, 2017

6 months and nothing??? Where can we find what a Cloud Scheduled Event Object should look like so we can create our own class??

@normj
Copy link
Member

normj commented May 23, 2017

Sorry, we haven't made a lot of progress on this one. The problem is the detail section of the message differs for every service that sends events. Plus you can also have custom events. Also there is not one page that describes what the event looks like for all of the services.

I have debated about doing something like:

public class ECSEventDetail
{
    public string ClusterArn {get;set;}
    ...
}

public class CloudWatchevent<T>
{
    public string Version {get;set;}
    ...
    public T Detail {get;set;}
}

public async Task LambdaFunction(CloudWatchEvent<ECSEventDetail> event, ILambdaContext context)
{
    ...
}

I think this would solve the problem but we would run the risk of the detail event objects getting out of date or we would be missing some detail events.

If the community is okay with this. I can add the package. Pull request would be greatly appreciated to help keep the detail events updated.

@exocom
Copy link

exocom commented Jul 28, 2018

@normj I liked your comment about making this a generic class. For the time being you should have to supply your own class. If others want to make PRs for the different types of "Detail" then that would be great, however, I'm in favor of getting this in at least.

The PR #299 should cover the basics including deserializing "DetailType". Also it has examples for different detail types documented.

@Kralizek
Copy link

Great job @exocom ! would it be possible to change it so there is a non-generic base class that doesn't offer the Details property and a generic subclass with the generic Details property?

This would allow those that only need to react to the event with no interest to the details to use this class with no extra coding.

example

public class CloudWatchevent
{
    ....
}

public async Task LambdaFunction(CloudWatchEvent event, ILambdaContext context)
{
    ...
}

public class CloudWatchevent<T> : CloudWatchevent
{
   public T Detail {get;set;}
}

public class ECSEventDetail
{
    public string ClusterArn {get;set;}
    ...
}

public async Task LambdaFunction(CloudWatchEvent<ECSEventDetail> event, ILambdaContext context)
{
    ...
}

@exocom
Copy link

exocom commented Jul 28, 2018

@Kralizek I found a useful documentation page which made me realize a way to do this in an extensible manor. I also found another documentation page that has 27 events with their specific Detail Objects IE the schemas.

Like your idea, but want to offer a solution that is flexible enough to receive multiple types of events. So how about an interface with concrete classes? I believe it would satisfy most use cases.

// All events 27 total, which conform to a common Interface.
// https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/EventTypes.html

namespace Amazon.Lambda.CloudWatchEvents
{
    // https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/CloudWatchEventsandEventPatterns.html
    public interface ICloudWatchEvent<T>
    {
        string Version { get; set; }
        string Account { get; set; }
        string Region { get; set; }
        T Detail { get; set; }
        string DetailType { get; set; }
        string Source { get; set; }
        DateTime Time { get; set; }
        string Id { get; set; }
        List<string> Resources { get; set; }
    }
}

namespace Amazon.Lambda.ScheduledEvents
{
    // Scheduled Event
    // https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/EventTypes.html#schedule_event_type
    
    public class Detail
    {

    }
    
    public class ScheduledEvent : ICloudWatchEvent<Detail>
    {
        public string Version { get; set; }
        public string Account { get; set; }
        public string Region { get; set; }
        public Detail Detail { get; set; }
        public string DetailType { get; set; }
        public string Source { get; set; }
        public DateTime Time { get; set; }
        public string Id { get; set; }
        public List<string> Resources { get; set; }
    }
}

namespace Amazon.Lambda.ECSEvents
{
    // ECS Event
    // https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_cwe_events.html

    public class Attribute
    {
        public string Name { get; set; }
    }

    public class RegisteredResource
    {
        public string Name { get; set; }
        public string Type { get; set; }
        public int IntegerValue { get; set; }
        public List<object> StringSetValue { get; set; }
    }

    public class RemainingResource
    {
        public string name { get; set; }
        public string type { get; set; }
        public int integerValue { get; set; }
        public List<object> stringSetValue { get; set; }
    }

    public class VersionInfo
    {
        public string AgentHash { get; set; }
        public string AgentVersion { get; set; }
        public string DockerVersion { get; set; }
    }

    public class Detail
    {
        public bool AgentConnected { get; set; }
        public List<Attribute> Attributes { get; set; }
        public string ClusterArn { get; set; }
        public string EontainerInstanceArn { get; set; }
        public string Ec2InstanceId { get; set; }
        public List<RegisteredResource> RegisteredResources { get; set; }
        public List<RemainingResource> RemainingResources { get; set; }
        public string Status { get; set; }
        public int Version { get; set; }
        public VersionInfo VersionInfo { get; set; }
        public DateTime UpdatedAt { get; set; }
    }

    public class ECSEvent : ICloudWatchEvent<Detail>
    {
        public string Version { get; set; }
        public string Id { get; set; }
        public string DetailType { get; set; }
        public string Source { get; set; }
        public string Account { get; set; }
        public DateTime Time { get; set; }
        public string Region { get; set; }
        public List<string> Resources { get; set; }
        public Detail Detail { get; set; }
    }
}

// ... Other 25 events get concrete classes.

If you only have 1 Event Type

public async Task LambdaFunction(ScheduledEvent @event, ILambdaContext context)
{
...
}

If you have multiple Event Types

public void LambdaFunction(ICloudWatchEvent<object> @event)
{
    switch(@event.DetailType) {
        case "ECS Task State Change":
            var ecsEvent = JsonConvert.DeserializeObject<ECSEvent>(@event);
            break;
        case null:
            break;
    }
    ...
}

If you have custom CloudWatch Event

public class CustomDetail {
    public string Name { get; set; }
}
public void LambdaFunction(ICloudWatchEvent<CustomDetail> @event)
{
   var isKalarrs = @event.Detai.Name == "kalarrs";
    ...
}

If you have your own custom Event

public class CustomData {
    public string Name { get; set; }
}
public void LambdaFunction(CustomData @event)
{
   var isKalarrs = @event.Name == "kalarrs";
    ...
}

@Kralizek
Copy link

I see where you are coming from. I personally dislike using interfaces in this case because I find them semantic-rich in a operation-based context.

Also I am not convinced about having a ’Details’ property void of any semantic in the "quick to use" case.

Just my 2c, but please wait for an opinion from the maintainers.

This was referenced Sep 24, 2018
@diehlaws diehlaws added feature-request A feature should be added or improved. and removed Enhancement labels Jan 3, 2019
@normj normj closed this as completed in #327 Feb 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request A feature should be added or improved.
Projects
None yet
Development

No branches or pull requests

7 participants