github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/event/parser.go (about) 1 package event 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "reflect" 7 "strings" 8 9 "github.com/pf-qiu/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(SetPipelineChanged{}) 47 RegisterEvent(Status{}) 48 RegisterEvent(SelectedWorker{}) 49 RegisterEvent(Log{}) 50 RegisterEvent(Error{}) 51 RegisterEvent(ImageCheck{}) 52 RegisterEvent(ImageGet{}) 53 54 // deprecated: 55 RegisterEvent(InitializeV10{}) 56 RegisterEvent(FinishV10{}) 57 RegisterEvent(StartV10{}) 58 RegisterEvent(InputV10{}) 59 RegisterEvent(InputV20{}) 60 RegisterEvent(OutputV10{}) 61 RegisterEvent(OutputV20{}) 62 RegisterEvent(ErrorV10{}) 63 RegisterEvent(ErrorV20{}) 64 RegisterEvent(ErrorV30{}) 65 RegisterEvent(FinishTaskV10{}) 66 RegisterEvent(FinishTaskV20{}) 67 RegisterEvent(FinishTaskV30{}) 68 RegisterEvent(InitializeTaskV10{}) 69 RegisterEvent(InitializeTaskV20{}) 70 RegisterEvent(InitializeTaskV30{}) 71 RegisterEvent(StartTaskV10{}) 72 RegisterEvent(StartTaskV20{}) 73 RegisterEvent(StartTaskV30{}) 74 RegisterEvent(StartTaskV40{}) 75 RegisterEvent(LogV10{}) 76 RegisterEvent(LogV20{}) 77 RegisterEvent(LogV30{}) 78 RegisterEvent(LogV40{}) 79 RegisterEvent(FinishGetV10{}) 80 RegisterEvent(FinishGetV20{}) 81 RegisterEvent(FinishGetV30{}) 82 RegisterEvent(FinishPutV10{}) 83 RegisterEvent(FinishPutV20{}) 84 RegisterEvent(FinishPutV30{}) 85 RegisterEvent(InitializeGetV10{}) 86 RegisterEvent(InitializePutV10{}) 87 RegisterEvent(FinishGetV40{}) 88 RegisterEvent(FinishPutV40{}) 89 } 90 91 type Message struct { 92 Event atc.Event 93 } 94 95 type Envelope struct { 96 Data *json.RawMessage `json:"data"` 97 Event atc.EventType `json:"event"` 98 Version atc.EventVersion `json:"version"` 99 } 100 101 func (m Message) MarshalJSON() ([]byte, error) { 102 var envelope Envelope 103 104 payload, err := json.Marshal(m.Event) 105 if err != nil { 106 return nil, err 107 } 108 109 envelope.Data = (*json.RawMessage)(&payload) 110 envelope.Event = m.Event.EventType() 111 envelope.Version = m.Event.Version() 112 113 return json.Marshal(envelope) 114 } 115 116 func (m *Message) UnmarshalJSON(bytes []byte) error { 117 var envelope Envelope 118 119 err := json.Unmarshal(bytes, &envelope) 120 if err != nil { 121 return err 122 } 123 124 event, err := ParseEvent(envelope.Version, envelope.Event, *envelope.Data) 125 if err != nil { 126 return err 127 } 128 129 m.Event = event 130 131 return nil 132 } 133 134 type UnknownEventTypeError struct { 135 Type atc.EventType 136 } 137 138 func (err UnknownEventTypeError) Error() string { 139 return fmt.Sprintf("unknown event type: %s", err.Type) 140 } 141 142 type UnknownEventVersionError struct { 143 Type atc.EventType 144 Version atc.EventVersion 145 KnownVersions []string 146 } 147 148 func (err UnknownEventVersionError) Error() string { 149 return fmt.Sprintf( 150 "unknown event version: %s version %s (supported versions: %s)", 151 err.Type, 152 err.Version, 153 strings.Join(err.KnownVersions, ", "), 154 ) 155 } 156 157 func ParseEvent(version atc.EventVersion, typ atc.EventType, payload []byte) (atc.Event, error) { 158 versions, found := events[typ] 159 if !found { 160 return nil, UnknownEventTypeError{typ} 161 } 162 163 knownVersions := []string{} 164 for v, parser := range versions { 165 knownVersions = append(knownVersions, string(v)) 166 167 if v.IsCompatibleWith(version) { 168 return parser(payload) 169 } 170 } 171 172 return nil, UnknownEventVersionError{ 173 Type: typ, 174 Version: version, 175 KnownVersions: knownVersions, 176 } 177 }