github.com/chenbh/concourse/v6@v6.4.2/atc/event/parser.go (about) 1 package event 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "reflect" 7 "strings" 8 9 "github.com/chenbh/concourse/v6/atc" 10 ) 11 12 type eventTable map[atc.EventType]eventVersions 13 type eventVersions map[atc.EventVersion]eventParser 14 type eventParser func([]byte) (atc.Event, error) 15 16 var events = eventTable{} 17 18 func unmarshaler(e atc.Event) func([]byte) (atc.Event, error) { 19 return func(payload []byte) (atc.Event, error) { 20 val := reflect.New(reflect.TypeOf(e)) 21 err := json.Unmarshal(payload, val.Interface()) 22 return val.Elem().Interface().(atc.Event), err 23 } 24 } 25 26 func RegisterEvent(e atc.Event) { 27 versions, found := events[e.EventType()] 28 if !found { 29 versions = eventVersions{} 30 events[e.EventType()] = versions 31 } 32 33 versions[e.Version()] = unmarshaler(e) 34 } 35 36 func init() { 37 RegisterEvent(InitializeTask{}) 38 RegisterEvent(StartTask{}) 39 RegisterEvent(FinishTask{}) 40 RegisterEvent(InitializeGet{}) 41 RegisterEvent(StartGet{}) 42 RegisterEvent(FinishGet{}) 43 RegisterEvent(InitializePut{}) 44 RegisterEvent(StartPut{}) 45 RegisterEvent(FinishPut{}) 46 RegisterEvent(Status{}) 47 RegisterEvent(SelectedWorker{}) 48 RegisterEvent(Log{}) 49 RegisterEvent(Error{}) 50 51 // deprecated: 52 RegisterEvent(InitializeV10{}) 53 RegisterEvent(FinishV10{}) 54 RegisterEvent(StartV10{}) 55 RegisterEvent(InputV10{}) 56 RegisterEvent(InputV20{}) 57 RegisterEvent(OutputV10{}) 58 RegisterEvent(OutputV20{}) 59 RegisterEvent(ErrorV10{}) 60 RegisterEvent(ErrorV20{}) 61 RegisterEvent(ErrorV30{}) 62 RegisterEvent(FinishTaskV10{}) 63 RegisterEvent(FinishTaskV20{}) 64 RegisterEvent(FinishTaskV30{}) 65 RegisterEvent(InitializeTaskV10{}) 66 RegisterEvent(InitializeTaskV20{}) 67 RegisterEvent(InitializeTaskV30{}) 68 RegisterEvent(StartTaskV10{}) 69 RegisterEvent(StartTaskV20{}) 70 RegisterEvent(StartTaskV30{}) 71 RegisterEvent(StartTaskV40{}) 72 RegisterEvent(LogV10{}) 73 RegisterEvent(LogV20{}) 74 RegisterEvent(LogV30{}) 75 RegisterEvent(LogV40{}) 76 RegisterEvent(FinishGetV10{}) 77 RegisterEvent(FinishGetV20{}) 78 RegisterEvent(FinishGetV30{}) 79 RegisterEvent(FinishPutV10{}) 80 RegisterEvent(FinishPutV20{}) 81 RegisterEvent(FinishPutV30{}) 82 RegisterEvent(InitializeGetV10{}) 83 RegisterEvent(InitializePutV10{}) 84 RegisterEvent(FinishGetV40{}) 85 RegisterEvent(FinishPutV40{}) 86 } 87 88 type Message struct { 89 Event atc.Event 90 } 91 92 type Envelope struct { 93 Data *json.RawMessage `json:"data"` 94 Event atc.EventType `json:"event"` 95 Version atc.EventVersion `json:"version"` 96 } 97 98 func (m Message) MarshalJSON() ([]byte, error) { 99 var envelope Envelope 100 101 payload, err := json.Marshal(m.Event) 102 if err != nil { 103 return nil, err 104 } 105 106 envelope.Data = (*json.RawMessage)(&payload) 107 envelope.Event = m.Event.EventType() 108 envelope.Version = m.Event.Version() 109 110 return json.Marshal(envelope) 111 } 112 113 func (m *Message) UnmarshalJSON(bytes []byte) error { 114 var envelope Envelope 115 116 err := json.Unmarshal(bytes, &envelope) 117 if err != nil { 118 return err 119 } 120 121 event, err := ParseEvent(envelope.Version, envelope.Event, *envelope.Data) 122 if err != nil { 123 return err 124 } 125 126 m.Event = event 127 128 return nil 129 } 130 131 type UnknownEventTypeError struct { 132 Type atc.EventType 133 } 134 135 func (err UnknownEventTypeError) Error() string { 136 return fmt.Sprintf("unknown event type: %s", err.Type) 137 } 138 139 type UnknownEventVersionError struct { 140 Type atc.EventType 141 Version atc.EventVersion 142 KnownVersions []string 143 } 144 145 func (err UnknownEventVersionError) Error() string { 146 return fmt.Sprintf( 147 "unknown event version: %s version %s (supported versions: %s)", 148 err.Type, 149 err.Version, 150 strings.Join(err.KnownVersions, ", "), 151 ) 152 } 153 154 func ParseEvent(version atc.EventVersion, typ atc.EventType, payload []byte) (atc.Event, error) { 155 versions, found := events[typ] 156 if !found { 157 return nil, UnknownEventTypeError{typ} 158 } 159 160 knownVersions := []string{} 161 for v, parser := range versions { 162 knownVersions = append(knownVersions, string(v)) 163 164 if v.IsCompatibleWith(version) { 165 return parser(payload) 166 } 167 } 168 169 return nil, UnknownEventVersionError{ 170 Type: typ, 171 Version: version, 172 KnownVersions: knownVersions, 173 } 174 }