2016-10-07 9 views
0

Я использую confd для динамической реинжиниринга сервиса nginx и немного борюсь с шаблонами Go. У меня есть json-объект с именем $data, а $data.subsets может содержать ключ с именем 'addresses' - я хочу только выполнить шаблон внутри цикла, если это условие выполнено.Шаблоны Go - проверьте, существует ли ключ в списке json

Я пробовал различные вещи, такие как $data.subsets[0].addresses, которые вы видите ниже, что совершенно неправильно. Я не совсем уверен, как это можно сделать правильно.

Это часть моего шаблона nginx, которую я хочу отобразить только в том случае, если есть хотя бы один восходящий сервис, а не если нет/недоступен.

Следующее за шаблоном - объекты json для $data при успешном проступке.

Заранее благодарю вас за помощь, мы очень благодарны!

{{ range $ns := getvs "/registry/services/endpoints/*/app" }} 
{{ $data := json $ns }} 
    {{ if $data.subsets[0].addresses }} 
upstream {{ $data.metadata.namespace }}_{{ $data.metadata.name }}_pool { 
     {{ range $subset := $data.subsets }}{{ range $ref := $subset.addresses }}{{ range $portConfig := $subset.ports }} 
server {{ $ref.ip }}:{{ $portConfig.port }}; 
     {{ end }}{{ end }}{{ end }} 
} 
    {{ end }} 
{{ end }} 

Пример $data, когда нет Бобы запланированных:

{ 
    "kind":"Endpoints", 
    "apiVersion":"v1", 
    "metadata":{ 
     "name":"app", 
     "namespace":"ns1", 
     "selfLink":"/api/v1/namespaces/ns1/endpoints/app", 
     "labels":{ 
     "app":"app" 
     } 
    }, 
    "subsets":[] 
} 

Пример $data, когда есть стручки работает, но не здоров:

{ 
    "kind":"Endpoints", 
    "apiVersion":"v1", 
    "metadata":{ 
     "name":"app", 
     "namespace":"ns1", 
     "labels":{ 
     "app":"app" 
     } 
    }, 
    "subsets":[ 
     { 
     "notReadyAddresses":[ 
      { 
       "ip":"10.254.60.5", 
       "targetRef":{ 
        "kind":"Pod", 
        "namespace":"ns1", 
        "name":"app-421757659-83rfg", 
       } 
      } 
     ], 
     "ports":[ 
      { 
       "name":"ns1-app-8080", 
       "port":8080, 
       "protocol":"TCP" 
      } 
     ] 
     } 
    ] 
} 

Пример $data, когда есть стручки работает и доступен. Это единственное условие, которое я хочу встретить для итерации шаблона для рендеринга.

{ 
    "kind":"Endpoints", 
    "apiVersion":"v1", 
    "metadata":{ 
     "name":"app", 
     "namespace":"ns1", 
     "selfLink":"/api/v1/namespaces/ns1/endpoints/app", 
     "labels":{ 
     "app":"app" 
     } 
    }, 
    "subsets":[ 
     { 
     "addresses":[ 
      { 
       "ip":"10.254.18.11", 
       "targetRef":{ 
        "kind":"Pod", 
        "namespace":"ns1", 
        "name":"app-3869480132-kfthi" 
       } 
      }, 
      { 
       "ip":"10.254.18.9", 
       "targetRef":{ 
        "kind":"Pod", 
        "namespace":"ns1", 
        "name":"app-3869480132-9bufk" 
       } 
      } 
     ], 
     "ports":[ 
      { 
       "name":"ns1-app-8080", 
       "port":8080, 
       "protocol":"TCP" 
      } 
     ] 
     } 
    ] 
} 
+0

Почему вы не проверяете условие в нормальном коде Go с нормальной обработкой json, а затем просто передаете bool в шаблон? Доступ к значениям в вашем json довольно прямолинейный, независимо от того, какой вариант он, однако, я не уверен, как вы это сделаете, учитывая библиотеки в игре в этом контексте. Если объект '$ data' сильно используется в другом месте, я не думаю, что он должен быть передан в шаблон вообще, поскольку большая часть его не имеет значения в этом контексте. На самом деле вам, вероятно, следует просто извлечь список адресов и передать их и не иметь этой логики в своем шаблоне. – evanmcdonnal

ответ

1

The $data.subsets[0].addresses является незаконным выражение шаблона (содержит [ и ]). Попробуйте следующее определение шаблона:

{{range $cfg := getvs "/registry/services/endpoints/*/app"}} 
{{$data := json $cfg}} 
{{range $data.subsets}}{{range $addr := .addresses}} 
{{with $ns := $addr.targetRef.namespace}} 
upstream {{$ns}}_{{$addr.targetRef.name}}_pool { 
    {{range $data.subsets}}{{range $port := .ports}} 
     {{/* 
      Split port.name then test if address namespace 
      match the port.name. Test Condition: 
      len($portDesc) > 0 && $portDesc[0] == $ns 
     */}} 
     {{$portDesc := split $port.name "-"}} 
     {{if and (gt (len $portDesc) 0) (eq (index $portDesc 0) $ns)}} 
    server {{ $addr.ip }}:{{ $port.port }}; 
     {{end}} 
    {{end}}{{ end }} 
} 
{{end}} 
{{end}}{{end}} 

сгенерированный (после удаления пустых строк) для трех указанных выше данных JSon должно быть:

upstream ns1_app-3869480132-kfthi_pool { 
    server 10.254.18.11:8080; 
} 
upstream ns1_app-3869480132-9bufk_pool { 
    server 10.254.18.9:8080; 
} 

Ключ range действия в {{range $data.subsets}}{{range $addr := .addresses}}. Ничего не будет написано, если len конвейера (subsets10 или addresses) равно нулю, то есть когда subsets не содержит элемент или addresses - null (элемент подмножества addresses).