@@ -17,13 +17,23 @@ import struct Foundation.Date
17
17
/// EventBridge has the same payloads/notification types as CloudWatch
18
18
typealias EventBridge = Cloudwatch
19
19
20
+ public protocol CloudwatchDetail : Decodable {
21
+ static var name : String { get }
22
+ }
23
+
24
+ public extension CloudwatchDetail {
25
+ var detailType : String {
26
+ Self . name
27
+ }
28
+ }
29
+
20
30
public enum Cloudwatch {
21
31
/// CloudWatch.Event is the outer structure of an event sent via CloudWatch Events.
22
32
///
23
33
/// **NOTE**: For examples of events that come via CloudWatch Events, see
24
34
/// https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/EventTypes.html
25
35
/// https://docs.aws.amazon.com/eventbridge/latest/userguide/event-types.html
26
- public struct Event < Detail: Decodable > : Decodable {
36
+ public struct Event < Detail: CloudwatchDetail > : Decodable {
27
37
public let id : String
28
38
public let source : String
29
39
public let accountId : String
@@ -39,6 +49,7 @@ public enum Cloudwatch {
39
49
case time
40
50
case region
41
51
case resources
52
+ case detailType = " detail-type "
42
53
case detail
43
54
}
44
55
@@ -51,61 +62,28 @@ public enum Cloudwatch {
51
62
self . time = ( try container. decode ( ISO8601Coding . self, forKey: . time) ) . wrappedValue
52
63
self . region = try container. decode ( AWSRegion . self, forKey: . region)
53
64
self . resources = try container. decode ( [ String ] . self, forKey: . resources)
54
- self . detail = ( try DetailCoding ( from: decoder) ) . guts
55
- }
56
65
57
- private struct DetailCoding {
58
- public let guts : Detail
59
-
60
- internal enum CodingKeys : String , CodingKey {
61
- case detailType = " detail-type "
62
- case detail
66
+ let detailType = try container. decode ( String . self, forKey: . detailType)
67
+ guard detailType == Detail . name else {
68
+ throw PayloadTypeMismatch ( name: detailType, type: Detail . self)
63
69
}
64
70
65
- public init ( from decoder: Decoder ) throws {
66
- let container = try decoder. container ( keyedBy: CodingKeys . self)
67
- let detailType = try container. decode ( String . self, forKey: . detailType)
68
- let detailFactory : ( Decoder ) throws -> Decodable
69
- switch detailType {
70
- case ScheduledEvent . name:
71
- detailFactory = Empty . init
72
- case EC2 . InstanceStateChangeNotificationEvent. name:
73
- detailFactory = EC2 . InstanceStateChangeNotification. init
74
- case EC2 . SpotInstanceInterruptionNoticeEvent. name:
75
- detailFactory = EC2 . SpotInstanceInterruptionNotice. init
76
- default :
77
- guard let factory = Cloudwatch . detailPayloadRegistry [ detailType] else {
78
- throw UnknownPayload ( name: detailType)
79
- }
80
- detailFactory = factory
81
- }
82
- let detailsDecoder = try container. superDecoder ( forKey: . detail)
83
- guard let detail = try detailFactory ( detailsDecoder) as? Detail else {
84
- throw PayloadTypeMismatch ( name: detailType, type: Detail . self)
85
- }
86
- self . guts = detail
87
- }
71
+ self . detail = try container. decode ( Detail . self, forKey: . detail)
88
72
}
89
73
}
90
74
91
- // MARK: - Detail Payload Registry
92
-
93
- // FIXME: make thread safe
94
- private static var detailPayloadRegistry = [ String : ( Decoder ) throws -> Decodable ] ( )
95
-
96
- public static func registerDetailPayload< T: Decodable > ( label: String , type: T . Type ) {
97
- detailPayloadRegistry [ label] = type. init
98
- }
99
-
100
75
// MARK: - Common Event Types
101
76
102
- public typealias ScheduledEvent = Event < Empty >
103
-
104
- public struct Empty : Decodable { }
77
+ public typealias ScheduledEvent = Event < Scheduled >
78
+ public struct Scheduled : CloudwatchDetail {
79
+ public static let name = " Scheduled Event "
80
+ }
105
81
106
82
public enum EC2 {
107
83
public typealias InstanceStateChangeNotificationEvent = Event < InstanceStateChangeNotification >
108
- public struct InstanceStateChangeNotification : Decodable {
84
+ public struct InstanceStateChangeNotification : CloudwatchDetail {
85
+ public static let name = " EC2 Instance State-change Notification "
86
+
109
87
public enum State : String , Codable {
110
88
case running
111
89
case shuttingDown = " shutting-down "
@@ -124,7 +102,9 @@ public enum Cloudwatch {
124
102
}
125
103
126
104
public typealias SpotInstanceInterruptionNoticeEvent = Event < SpotInstanceInterruptionNotice >
127
- public struct SpotInstanceInterruptionNotice : Decodable {
105
+ public struct SpotInstanceInterruptionNotice : CloudwatchDetail {
106
+ public static let name = " EC2 Spot Instance Interruption Warning "
107
+
128
108
public enum Action : String , Codable {
129
109
case hibernate
130
110
case stop
@@ -150,15 +130,3 @@ public enum Cloudwatch {
150
130
let type : Any
151
131
}
152
132
}
153
-
154
- extension Cloudwatch . ScheduledEvent {
155
- static var name : String { " Scheduled Event " }
156
- }
157
-
158
- extension Cloudwatch . EC2 . InstanceStateChangeNotificationEvent {
159
- static var name : String { " EC2 Instance State-change Notification " }
160
- }
161
-
162
- extension Cloudwatch . EC2 . SpotInstanceInterruptionNoticeEvent {
163
- static var name : String { " EC2 Spot Instance Interruption Warning " }
164
- }
0 commit comments