11package webhooks
22
33import (
4- "bufio "
4+ "encoding/json "
55 "errors"
66 "fmt"
77 "io"
@@ -20,11 +20,16 @@ var (
2020 `
2121invalid format.
2222valid formats should look like:
23- [put|post],functionName,https_url
24- delete,functionName
23+ {"hooks": [OPERATION]}
2524
26- [put|post],className:triggerName,https_url
27- delete,className:triggerName
25+ OPERATION ->
26+ {"op": "put", "function": {"functionName": "name", "url": "https_url"}}
27+ {"op": "post", "function": {"functionName": "name", "url": "https_url"}}
28+ {"op": "delete", "function": {"functionName": "name"}}
29+
30+ {"op": "put", "trigger": {"className": "cname", "triggerName": "tname", "url":"https_url"}}
31+ {"op": "post", "trigger": {"className": "cname", "triggerName": "tname", "url":"https_url"}}
32+ {"op": "delete", "trigger": {"className": "cname", "triggerName": "tname",}}
2833` )
2934
3035 errPostToPut = errors .New (
@@ -41,9 +46,9 @@ delete,className:triggerName
4146)
4247
4348type hookOperation struct {
44- method string
45- function * functionHook
46- trigger * triggerHook
49+ Method string `json:"op,omitempty"`
50+ Function * functionHook `json:"function,omitempty"`
51+ Trigger * triggerHook `json:"trigger,omitempty"`
4752}
4853
4954func validateURL (urlStr string ) error {
@@ -98,162 +103,61 @@ func (h *Hooks) checkTriggerName(s string) error {
98103 )
99104}
100105
101- func (h * Hooks ) postOrPutHook (
106+ func (h * Hooks ) appendHookOperation (
102107 e * parsecli.Env ,
108+ hookOp * hookOperation ,
103109 hooksOps []* hookOperation ,
104- fields ... string ,
105110) (bool , []* hookOperation , error ) {
106- restOp := strings .ToUpper (fields [0 ])
107- if restOp != "POST" && restOp != "PUT" {
108- return false , nil , stackerr .Wrap (errInvalidFormat )
109- }
110-
111- switch len (fields ) {
112- case 3 :
113- hooksOps = append (hooksOps , & hookOperation {
114- method : restOp ,
115- function : & functionHook {FunctionName : fields [1 ], URL : fields [2 ]},
116- })
117- return true , hooksOps , nil
118-
119- case 4 :
120- if err := h .checkTriggerName (fields [2 ]); err != nil {
121- return false , nil , err
122- }
123- hooksOps = append (hooksOps , & hookOperation {
124- method : restOp ,
125- trigger : & triggerHook {ClassName : fields [1 ], TriggerName : fields [2 ], URL : fields [3 ]},
126- })
127- return true , hooksOps , nil
111+ if hookOp == nil || (hookOp .Function == nil && hookOp .Trigger == nil ) ||
112+ (hookOp .Function != nil && hookOp .Trigger != nil ) {
113+ return false , hooksOps , nil
128114 }
129- return false , nil , stackerr .Wrap (errInvalidFormat )
130-
131- }
132115
133- func (h * Hooks ) deleteHook (
134- e * parsecli.Env ,
135- hooksOps []* hookOperation ,
136- fields ... string ,
137- ) (bool , []* hookOperation , error ) {
138- restOp := strings .ToUpper (fields [0 ])
139- if restOp != "DELETE" {
116+ method := strings .ToUpper (hookOp .Method )
117+ if method != "POST" && method != "PUT" && method != "DELETE" {
140118 return false , nil , stackerr .Wrap (errInvalidFormat )
141119 }
142120
143- switch len (fields ) {
144- case 2 :
145- hooksOps = append (hooksOps , & hookOperation {
146- method : "DELETE" ,
147- function : & functionHook {FunctionName : fields [1 ]},
148- })
149- return true , hooksOps , nil
150- case 3 :
151- if err := h .checkTriggerName (fields [2 ]); err != nil {
121+ hookOp .Method = method
122+ if hookOp .Trigger != nil {
123+ if err := h .checkTriggerName (hookOp .Trigger .TriggerName ); err != nil {
152124 return false , nil , err
153125 }
154- hooksOps = append (hooksOps , & hookOperation {
155- method : "DELETE" ,
156- trigger : & triggerHook {ClassName : fields [1 ], TriggerName : fields [2 ]},
157- })
158- return true , hooksOps , nil
159- }
160-
161- return false , nil , stackerr .Wrap (errInvalidFormat )
162- }
163-
164- func (h * Hooks ) appendHookOperation (
165- e * parsecli.Env ,
166- fields []string ,
167- hooks []* hookOperation ,
168- ) (bool , []* hookOperation , error ) {
169- if len (fields ) == 0 {
170- return false , hooks , nil
171- }
172-
173- switch strings .ToLower (fields [0 ]) {
174- case "post" , "put" :
175- return h .postOrPutHook (e , hooks , fields ... )
176-
177- case "delete" :
178- return h .deleteHook (e , hooks , fields ... )
179- }
180- return false , nil , stackerr .Wrap (errInvalidFormat )
181- }
182-
183- func (h * Hooks ) processHooksOperation (e * parsecli.Env , op string ) ([]string , error ) {
184- op = strings .TrimSpace (op )
185- if op == "" {
186- return nil , nil
187- }
188-
189- fields := strings .SplitN (op , "," , 3 )
190- switch restOp := strings .ToLower (fields [0 ]); restOp {
191- case "post" , "put" :
192- if len (fields ) < 3 {
193- return nil , stackerr .Wrap (errInvalidFormat )
194- }
195- case "delete" :
196- if len (fields ) != 2 {
197- return nil , stackerr .Wrap (errInvalidFormat )
198- }
199- subFields := strings .SplitN (fields [1 ], ":" , 2 )
200- if len (subFields ) == 2 {
201- fields = append (fields , subFields [1 ])
202- fields [1 ] = subFields [0 ]
203- }
204- return fields , nil
205- default :
206- return nil , stackerr .Wrap (errInvalidFormat )
207- }
208-
209- if h .baseWebhookURL != nil {
210- u , err := h .baseWebhookURL .Parse (fields [2 ])
211- if err != nil {
212- return nil , stackerr .Wrap (err )
213- }
214- fields [2 ] = u .String ()
215126 }
216127
217- switch subFields := strings .SplitN (fields [1 ], ":" , 2 ); len (subFields ) {
218- case 1 :
219- return fields , nil
220- case 2 :
221- fields = append (fields , fields [2 ])
222- fields [3 ] = fields [2 ]
223- fields [2 ] = subFields [1 ]
224- fields [1 ] = subFields [0 ]
225- return fields , nil
226- }
227- return nil , stackerr .Wrap (errInvalidFormat )
128+ hooksOps = append (hooksOps , hookOp )
129+ return true , hooksOps , nil
228130}
229131
230132func (h * Hooks ) createHooksOperations (
231133 e * parsecli.Env ,
232134 reader io.Reader ,
233135) ([]* hookOperation , error ) {
234- scanner := bufio .NewScanner (reader )
136+ var input struct {
137+ HooksOps []* hookOperation `json:"hooks,omitempty"`
138+ }
139+ err := json .NewDecoder (ioutil .NopCloser (reader )).Decode (& input )
140+ if err != nil {
141+ return nil , stackerr .Wrap (err )
142+ }
143+
235144 var (
236145 hooksOps []* hookOperation
237146 added bool
238147 )
239- lineNum := 0
240- for scanner .Scan () {
241- lineNum ++
242- fields , err := h .processHooksOperation (e , scanner .Text ())
243- if err != nil {
244- return nil , err
245- }
246- added , hooksOps , err = h .appendHookOperation (e , fields , hooksOps )
148+ for _ , hookOp := range input .HooksOps {
149+ added , hooksOps , err = h .appendHookOperation (e , hookOp , hooksOps )
247150 if err != nil {
248151 return nil , err
249152 }
250153 if ! added {
251- fmt .Fprintf (e .Out , "Ignoring line: %d\n " , lineNum )
154+ op , err := json .MarshalIndent (hookOp , "" , " " )
155+ if err == nil {
156+ fmt .Fprintf (e .Out , "Ignoring hook operation: \n %s\n " , op )
157+ }
252158 }
253159 }
254- if err := scanner .Err (); err != nil {
255- return nil , stackerr .Wrap (err )
256- }
160+
257161 return hooksOps , nil
258162}
259163
@@ -305,20 +209,20 @@ func (h *Hooks) functionHookExists(e *parsecli.Env, name string) (bool, error) {
305209}
306210
307211func (h * Hooks ) deployFunctionHook (e * parsecli.Env , op * hookOperation ) error {
308- if op .function == nil {
212+ if op .Function == nil {
309213 return stackerr .New ("cannot deploy nil function hook" )
310214 }
311- exists , err := h .functionHookExists (e , op .function .FunctionName )
215+ exists , err := h .functionHookExists (e , op .Function .FunctionName )
312216 if err != nil {
313217 return err
314218 }
315219
316- restOp , suppressed , err := h .checkStrictMode (op .method , exists )
220+ restOp , suppressed , err := h .checkStrictMode (op .Method , exists )
317221 if err != nil {
318222 return err
319223 }
320224
321- function := & functionHooksCmd {Function : op .function }
225+ function := & functionHooksCmd {Function : op .Function }
322226 switch restOp {
323227 case "POST" :
324228 return function .functionHooksCreate (e , nil )
@@ -357,20 +261,20 @@ func (h *Hooks) triggerHookExists(e *parsecli.Env, className, triggerName string
357261}
358262
359263func (h * Hooks ) deployTriggerHook (e * parsecli.Env , op * hookOperation ) error {
360- if op .trigger == nil {
264+ if op .Trigger == nil {
361265 return stackerr .New ("cannot deploy nil trigger hook" )
362266 }
363267
364- exists , err := h .triggerHookExists (e , op .trigger .ClassName , op .trigger .TriggerName )
268+ exists , err := h .triggerHookExists (e , op .Trigger .ClassName , op .Trigger .TriggerName )
365269 if err != nil {
366270 return err
367271 }
368- restOp , suppressed , err := h .checkStrictMode (op .method , exists )
272+ restOp , suppressed , err := h .checkStrictMode (op .Method , exists )
369273 if err != nil {
370274 return err
371275 }
372276
373- trigger := & triggerHooksCmd {Trigger : op .trigger , All : false }
277+ trigger := & triggerHooksCmd {Trigger : op .Trigger , All : false }
374278 switch restOp {
375279 case "POST" :
376280 return trigger .triggerHooksCreate (e , nil )
@@ -388,13 +292,13 @@ func (h *Hooks) deployTriggerHook(e *parsecli.Env, op *hookOperation) error {
388292
389293func (h * Hooks ) deployWebhooksConfig (e * parsecli.Env , hooksOps []* hookOperation ) error {
390294 for _ , op := range hooksOps {
391- if op .function == nil && op .trigger == nil {
295+ if op .Function == nil && op .Trigger == nil {
392296 return stackerr .New ("hook operation is neither a function, not a trigger." )
393297 }
394- if op .function != nil && op .trigger != nil {
298+ if op .Function != nil && op .Trigger != nil {
395299 return stackerr .New ("a hook cannot be both a function and a trigger." )
396300 }
397- if op .function != nil {
301+ if op .Function != nil {
398302 if err := h .deployFunctionHook (e , op ); err != nil {
399303 return err
400304 }
@@ -437,7 +341,7 @@ func (h *Hooks) HooksCmd(e *parsecli.Env, ctx *parsecli.Context, args []string)
437341 if err != nil {
438342 return stackerr .Wrap (err )
439343 }
440- reader = ioutil . NopCloser ( file )
344+ reader = file
441345 } else {
442346 fmt .Fprintln (e .Out , "Since a webhooks config file was not provided reading from stdin." )
443347 }
0 commit comments