I am using confd for a dynamic nginx service reconfiguration and having a bit of a struggle with the Go Templates. I have a json object named $data and $data.subsets may contain a key named 'addresses' -- I want to only execute the template inside the loop if that condition is met.
I've tried various things like the $data.subsets[0].addresses you see below which is completely wrong. I am not really sure how this can be done correctly.
This is a piece of my nginx template that I only want to render if there is at least 1 upstream service, not if there are none/unavailable.
Following the template is the json objects for $data on success any failure.
Thank you in advance for the help, it's greatly appreciated!
{{ 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 }}
Example of $data when there are no Pods scheduled:
{
"kind":"Endpoints",
"apiVersion":"v1",
"metadata":{
"name":"app",
"namespace":"ns1",
"selfLink":"/api/v1/namespaces/ns1/endpoints/app",
"labels":{
"app":"app"
}
},
"subsets":[]
}
Example of $data when there are pods running but not healthy:
{
"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"
}
]
}
]
}
Example of $data when there are pods running and available. This is the only condition I wish to meet for the iteration of the template to render.
{
"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"
}
]
}
]
}
The
$data.subsets[0].addressesis illegal template expression (contains[and]). Try the following template definition:Generated output(after removing empty lines) for the above three json data should be:
The key is
rangeaction in{{range $data.subsets}}{{range $addr := .addresses}}. Nothing will be written iflenof pipeline (subsetsoraddresses) is zero, i.e. whensubsetsdoes not contains element oraddressesisnull(no subsets element namedaddresses).