2016-10-07 3 views
0

ダイナミックなnginxサービスの再設定にはconfdを使用していますが、Goテンプレートとは少し苦労しています。 $dataという名前のjsonオブジェクトがあり、$data.subsetsに 'addresses'という名前のキーが含まれている可能性があります。その条件が満たされている場合にのみ、ループ内でテンプレートを実行します。テンプレートを移動する - jsonリストにキーが存在するかどうかを確認します

私は$data.subsets[0].addressesのようなさまざまなことを試しましたが、これは完全に間違っています。これがどうやって正しく行なわれるかわからない。

これは、少なくとも1つのアップストリームサービスがある場合にのみレンダリングしたいと思う私のnginxテンプレートの一部であり、存在しない/利用できない場合ではありません。

テンプレートに続くのは、成功した場合に$dataのjsonオブジェクトです。

ご協力いただきありがとうございます。大変感謝しています!

{{ 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の例:$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":[] 
} 

は例実行可能で利用可能です。これは、レンダリングするテンプレートの反復のために会いたい唯一の条件です。

{ 
    "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

通常のjson処理で通常のGoコードの状態をチェックしてから、boolをテンプレートに渡すのはなぜですか?あなたのjsonの値にアクセスすることはかなり変わりませんが、どのバリエーションにもかかわらず、私はあなたがその文脈で演奏されているライブラリをどのようにして行うのかは分かりません。 '$ data'オブジェクトが他の場所で頻繁に使われていない限り、私はそれがテンプレートに渡されるべきではないと考えています。なぜなら、その文脈ではほとんどが無関係であるからです。実際には、アドレスリストを抽出して渡すだけで、テンプレートにこのロジックが1つもないはずです。 – evanmcdonnal

答えて

1

$data.subsets[0].addressesは違法鋳型式([]を含有する)です。次のテンプレート定義を試してみてください:上記の3つのJSONデータ用(空行を削除した後)

{{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}} 

生成される出力は次のようになります。

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 $data.subsets}}{{range $addr := .addresses}}rangeアクションです。パイプライン(subsetsまたはaddresses)のlenがゼロである場合、つまり、subsetsに要素が含まれていない場合、またはaddressesが(サブセット要素addresses)でない場合は、何も書き込まれません。

関連する問題