@@ -18,6 +18,8 @@ import (
18
18
"strings"
19
19
"syscall"
20
20
"text/template"
21
+
22
+ "github.com/flosch/pongo2"
21
23
)
22
24
23
25
func exists (path string ) (bool , error ) {
@@ -453,6 +455,84 @@ func newTemplate(name string) *template.Template {
453
455
return tmpl
454
456
}
455
457
458
+ // Takes a template function that returns an error as its second return value,
459
+ // and returns a function that takes a pongo2 ExecutionContext as its first
460
+ // argument and calls ExecutionContext.OrigError() if the second return value
461
+ // of the original function is not nil when called. Otherwise returns the first
462
+ // return value.
463
+ func pongoWrap (fn interface {}) func (* pongo2.ExecutionContext , ... interface {}) interface {} {
464
+ fv := reflect .ValueOf (fn )
465
+ ft := reflect .TypeOf (fn )
466
+ return func (ctx * pongo2.ExecutionContext , args ... interface {}) interface {} {
467
+ if ft .NumIn () != len (args ) {
468
+ msg := fmt .Sprintf ("Wrong number of arguments; expected %d, got %d" , ft .NumIn (), len (args ))
469
+ return ctx .Error (msg , nil )
470
+ }
471
+ vals := make ([]reflect.Value , len (args ))
472
+ for i , v := range args {
473
+ vt := reflect .TypeOf (v )
474
+ if ! vt .ConvertibleTo (ft .In (i )) {
475
+ msg := fmt .Sprintf ("Wrong type for argument %d (got %s, expected %s)\n " , i , vt , ft .In (i ))
476
+ return ctx .Error (msg , nil )
477
+ }
478
+ vals [i ] = reflect .ValueOf (args [i ])
479
+ }
480
+ retvals := fv .Call (vals )
481
+ ret := retvals [0 ].Interface ()
482
+ err := retvals [1 ].Interface ()
483
+ if err != nil {
484
+ return ctx .OrigError (err .(error ), nil )
485
+ }
486
+ return ret
487
+ }
488
+ }
489
+
490
+ func pongoContext (containers Context ) pongo2.Context {
491
+ context := pongo2.Context {
492
+ "containers" : containers ,
493
+ "env" : containers .Env ,
494
+ "docker" : containers .Docker ,
495
+ "closest" : arrayClosest ,
496
+ "coalesce" : coalesce ,
497
+ "contains" : contains ,
498
+ "dict" : pongoWrap (dict ),
499
+ "dir" : pongoWrap (dirList ),
500
+ "exists" : pongoWrap (exists ),
501
+ "first" : arrayFirst ,
502
+ "groupBy" : pongoWrap (groupBy ),
503
+ "groupByKeys" : pongoWrap (groupByKeys ),
504
+ "groupByMulti" : pongoWrap (groupByMulti ),
505
+ "groupByLabel" : pongoWrap (groupByLabel ),
506
+ "hasPrefix" : hasPrefix ,
507
+ "hasSuffix" : hasSuffix ,
508
+ "json" : pongoWrap (marshalJson ),
509
+ "intersect" : intersect ,
510
+ "keys" : pongoWrap (keys ),
511
+ "last" : arrayLast ,
512
+ "replace" : strings .Replace ,
513
+ "parseBool" : strconv .ParseBool ,
514
+ "parseJson" : pongoWrap (unmarshalJson ),
515
+ "printf" : fmt .Sprintf ,
516
+ "queryEscape" : url .QueryEscape ,
517
+ "sha1" : hashSha1 ,
518
+ "split" : strings .Split ,
519
+ "splitN" : strings .SplitN ,
520
+ "trimPrefix" : trimPrefix ,
521
+ "trimSuffix" : trimSuffix ,
522
+ "trim" : trim ,
523
+ "when" : pongoWrap (when ),
524
+ "where" : pongoWrap (where ),
525
+ "whereExist" : pongoWrap (whereExist ),
526
+ "whereNotExist" : pongoWrap (whereNotExist ),
527
+ "whereAny" : pongoWrap (whereAny ),
528
+ "whereAll" : pongoWrap (whereAll ),
529
+ "whereLabelExists" : pongoWrap (whereLabelExists ),
530
+ "whereLabelDoesNotExist" : pongoWrap (whereLabelDoesNotExist ),
531
+ "whereLabelValueMatches" : pongoWrap (whereLabelValueMatches ),
532
+ }
533
+ return context
534
+ }
535
+
456
536
func filterRunning (config Config , containers Context ) Context {
457
537
if config .IncludeStopped {
458
538
return containers
@@ -486,7 +566,7 @@ func GenerateFile(config Config, containers Context) bool {
486
566
filteredContainers = filteredRunningContainers
487
567
}
488
568
489
- contents := executeTemplate (config .Template , filteredContainers )
569
+ contents := executeTemplate (config .Template , config . Engine , filteredContainers )
490
570
491
571
if ! config .KeepBlankLines {
492
572
buf := new (bytes.Buffer )
@@ -537,16 +617,29 @@ func GenerateFile(config Config, containers Context) bool {
537
617
return true
538
618
}
539
619
540
- func executeTemplate (templatePath string , containers Context ) []byte {
541
- tmpl , err := newTemplate (filepath .Base (templatePath )).ParseFiles (templatePath )
542
- if err != nil {
543
- log .Fatalf ("Unable to parse template: %s" , err )
544
- }
620
+ func executeTemplate (templatePath string , templateEngine string , containers Context ) []byte {
621
+ if templateEngine == "pongo2" {
622
+ context := pongoContext (containers )
623
+ tmpl , err := pongo2 .FromFile (templatePath )
624
+ if err != nil {
625
+ log .Fatalf ("Unable to parse template: %s" , err )
626
+ }
627
+ contents , err := tmpl .ExecuteBytes (context )
628
+ if err != nil {
629
+ log .Fatalf ("Template error: %s\n " , err )
630
+ }
631
+ return contents
632
+ } else {
633
+ tmpl , err := newTemplate (filepath .Base (templatePath )).ParseFiles (templatePath )
634
+ if err != nil {
635
+ log .Fatalf ("Unable to parse template: %s" , err )
636
+ }
545
637
546
- buf := new (bytes.Buffer )
547
- err = tmpl .ExecuteTemplate (buf , filepath .Base (templatePath ), & containers )
548
- if err != nil {
549
- log .Fatalf ("Template error: %s\n " , err )
638
+ buf := new (bytes.Buffer )
639
+ err = tmpl .ExecuteTemplate (buf , filepath .Base (templatePath ), & containers )
640
+ if err != nil {
641
+ log .Fatalf ("Template error: %s\n " , err )
642
+ }
643
+ return buf .Bytes ()
550
644
}
551
- return buf .Bytes ()
552
645
}
0 commit comments