{{- /* Default template for poundctl */ -}}
{{- /* Copyright (C) 2023, 2025 Sergey Poznyakoff
     *
     * Pound is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 3 of the License, or
     * (at your option) any later version.
     *
     * Pound is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with pound.  If not, see <http://www.gnu.org/licenses/>.
     */ -}}

{{define "hours" -}}
  {{div . 36e8 | printf "%02d:" -}}
  {{with mod . 36e8 -}}
    {{div . 6e7 | printf "%02d:" -}}
    {{with mod . 6e7 -}}
      {{div . 1e6 | printf "%02d" -}}
      {{mod . 1e6 | printf ".%06d" -}}
    {{end -}}
  {{end -}}
{{end -}}

{{define "duration" -}}
  {{if gt . 864e8}}{{div . 864e8}} days,
    {{- with mod . 864e8 }} {{template "hours" .}}{{end -}}
  {{else -}}
    {{template "hours" . -}}
  {{end -}}
{{end -}}

{{define "default.core" -}}
Server time: {{ .timestamp }}
{{if exists . "uptime" -}}
Uptime: {{ template "duration" .uptime }}
{{end -}}
Pound version: {{ .version }}
PID: {{ .pid }}
{{with .workers -}}
Workers:
  Min:     {{ .min }}
  Max:     {{ .max }}
  Current: {{ .count }}
  Active:  {{ .active }}
Idle timeout: {{ .timeout }}
{{end}}{{ /* with */ -}}
Queue: {{ if exists . "queue" }}{{with .queue}}
  Length:  {{ .len }}
  Max:     {{ .max }}
{{- end}}
{{- else -}}
{{ .queue_len -}}
{{end}}
{{end}}{{ /* define */ }}

{{define "milliseconds" -}}
{{ fdiv . 1000000 | printf "%.2f" }}
{{- end}}

{{define "default.pound" -}}
{{if exists . "core" -}}
{{block "default.core" .core}}
{{else -}}
{{block "default.core" .}}
{{end -}}
{{- /* Iterate over all listeners */ -}}
Listeners:

{{range $lno,$lstn = .listeners -}}
{{printf "%3d" $lno}}. {{block "default.print_listener" $lstn -}}
 Listener {{if .name}}"{{.name}}" {{end}}{{.protocol}}://{{.address}} {{if .enabled}}enabled{{else}}disabled{{end}}
 {{- /* For each listener, show all its services */ -}}
 {{block "default.print_services" .services}}
 {{- range $sno,$svc = .}}
   {{printf "%3d" $sno}}. {{block "default.print_service" $svc -}}
   Service {{if .name}}"{{.name}}" {{end}}{{if .enabled}}active{{else}}disabled{{end}}
  {{- /* List each backend in service */ -}}
  {{- range $bno,$backend = .backends}}
      {{printf "%3d" $bno}}. {{block "default.print_backend" $backend -}}
       {{.type}}
       {{- if exists . "weight" }} ({{.weight}}){{end}}
       {{- if exists . "parent"}} [mtx {{.parent}}]{{end}} {{if eq .type "backend" -}}
{{.protocol}} {{.address}} {{.priority}} {{if .alive}}alive{{else}}dead{{end}}
     {{- else if eq .type "matrix" -}}
"{{.hostname}}" {{.resolve_mode}} {{.family}} {{.priority}}
     {{- else if eq .type "redirect" -}}
{{.code}} {{.url}}{{if .redir_req}} (redirect request){{end}}
     {{- end}} {{if .enabled}}active{{else}}disabled{{end}}
     {{- if exists . "expire"}} [expires {{.expire}}]{{end}}
     {{- if exists . "stats"}} - {{with .stats -}}
       {{.request_count}} requests{{if gt .request_count 0}}, {{template "milliseconds" .request_time_avg}} ms avg, {{template "milliseconds" .request_time_stddev}} stddev{{end}}
       {{- end}}
     {{- end}}
   {{- end}}{{ /* block default.print_backend */ }}
  {{- end}}{{ /* iterating over backends */ }}
  {{- /* Show session type supported by the service */ }}
     Session type: {{.session_type}}
       {{- if len .sessions}}
	 {{- /* List all sessions */ }}
	 {{- range $i, $sess = .sessions}}
       {{$i}}. Session {{$sess.key}} {{$sess.backend}} {{$sess.expire}}
	 {{- end}}{{ /* ranging over sessions */ -}}
       {{end}}{{ /* if len */ }}
 {{- end}}{{ /* block default.print_service */ }}
 {{- end}}{{ /* iterating over services */ }}
 {{- end}}{{ /* block default.print_services */ }}
 {{- end}}{{ /* block default.print_listener */ }}
{{end}}{{ /* iterating over listeners */ }}
{{- if len .services}}
Global services:
{{block "default.print_services" .services}}
{{end -}}{{ /* if len .services */ }}
{{- end}}

{{define "default.log" -}}
  {{if .level}}{{.level}}{{else}}{{.global}} (global){{end}}
{{- end}}

{{define "default" -}}
  {{if exists . "kind" -}}
    {{- /* This is for v4.18 and later. */ -}}
    {{if eq .kind "pound" -}}
      {{block "default.pound" . -}}
    {{else if eq .kind "listener" -}}
      {{block "default.print_listener" . -}}
    {{else if eq .kind "service" -}}
      {{block "default.print_service" . -}}
    {{else if eq .kind "core" -}}
      {{block "default.core" . -}}
    {{else if eq .kind "backend" -}}
      {{block "default.print_backend" . -}}
    {{else if eq .kind "log" -}}
      {{block "default.log" . -}}
    {{else -}}
      Unsupported kind of object!
    {{end -}}
  {{else -}}
  {{- /* The code below is for pound versions prior to 4.18. It deduces
	 the type of object passed to it by presence of certain attributes:

	 "listeners"  -  entire listing as requested by poundctl list.
	 "services"   -  single listener as requested by poundctl list /L
			 Notice that this attribute is present in the full
			 listing as well, so presence of "listeners" should
			 be checked first.
	 "backends"   -  single service as requested by poundctl list /L/S.
	 "pid"        -  core status listing.

	 Otherwise, a backend listing (poundctl list /L/S/B) is assumed. */ -}}
    {{if exists . "listeners" -}}
      {{block "default.pound" . -}}
    {{else if exists . "services" -}}
      {{block "default.print_listener" . -}}
    {{else if exists . "backends" -}}
      {{block "default.print_service" . -}}
    {{else if exists . "pid" -}}
      {{block "default.core" . -}}
    {{else -}}
      {{block "default.print_backend" . -}}
    {{end -}}
  {{end}}
{{end -}}{{ /* define */ }}

{{define "xml.core" -}}
  <core>
    <timestamp>{{ .timestamp }}</timestamp>
    <server>
      <version>{{ .version }}</version>
      <pid>{{ .pid }}</pid>
      {{- if exists . "uptime"}}
      <uptime>{{ template "duration" .uptime }}</uptime>
      {{- end}}
    </server>
    <workers>
      {{with .workers -}}
      <min>{{ .min }}</min>
      <max>{{ .max }}</max>
      <current>{{ .count }}</current>
      <active>{{ .active }}</active>
      <timeout>{{ .timeout }}</timeout>
      {{- end -}}
    </workers>
    {{ if exists . "queue" }}{{with .queue}}<queue>
      <len>{{ .len }}</len>
      <max>{{ .max }}</max>
    </queue>
{{- end}}
{{- else}}<queue size="{{ .queue_len }}" />
{{- end}}
  </core>
{{- end}}

{{define "xml.pound" -}}
  {{- if exists . "core" }}
  {{- block "xml.core" .core}}
  {{- else}}
  {{- block "xml.core" .}}
  {{- end}}
  {{- /* Iterate over all listeners */ -}}
  {{- range $lno,$lstn = .listeners }}
    {{block "xml.print_listener" $lstn -}}
    <listener name="{{ .name }}" index="{{ $lno }}" protocol="{{ .protocol }}" address="{{ .address }}" status="{{if .enabled}}active{{else}}DISABLED{{end}}">
    {{- block "xml.print_services" .services}}
    {{- range $sno,$svc = . }}
      {{block "xml.print_service" $svc -}}
      <service {{if typeof $sno | ne "null"}}index="{{ $sno }}" {{end}}name="{{ .name }}" status="{{if .enabled}}active{{else}}DISABLED{{end}}" session_type="{{.session_type}}">
      {{- range $bno,$be = .backends }}
	{{block "xml.print_backend" $be -}}
	<backend index="{{ $bno }}" type="{{ .type }}"
	{{- if eq .type "backend"}} address="{{ .address }}"
	{{- else if eq .type "redirect"}} url="{{ .url }}" code="{{ .code }}"
	{{- end}} priority="{{ .priority }}" alive="{{if .alive}}yes{{else}}no{{end}}" status="{{if .enabled}}active{{else}}disabled{{end}}" />
	{{- end}}
      {{- end}}
	{{- range $i, $sess = .sessions}}
	<session index="{{$i}}" key="{{$sess.key}}" backend="{{$sess.backend}}" expire="{{$sess.expire}}" />
	{{- end}}
      </service>
    {{- end}}{{ /* block xml.print_service */ -}}
    {{end -}}
    {{end}}
    </listener>{{end -}}
  {{end -}}
  {{block "xml.print_services" .services }}
{{- end}}

{{define "xml" -}}
<pound>
  {{if exists . "kind" -}}
    {{if eq .kind "pound" -}}
      {{- /* This is a full listing. */ -}}
      {{block "xml.pound" . -}}
    {{else if eq .kind "listener" -}}
      {{- /* Single listener. */ -}}
      {{block "xml.print_listener" . -}}
    {{else if eq .kind "service" -}}
      {{- /* Single service. */ -}}
      {{block "xml.print_service" . -}}
    {{else if eq .kind "core" -}}
      {{- /* Core stat. */ -}}
      {{block "xml.core" . -}}
    {{else if eq .kind "backend" -}}
      {{- /* Backend listing. */ -}}
      {{block "xml.print_backend" . -}}
    {{else -}}
    <error>Missing or unsupported kind of object.</error>
    {{- end -}}
  {{else -}}
    {{if exists . "listeners" -}}
      {{block "xml.pound" . -}}
    {{else if exists . "services" -}}
      {{- /* Single listener. */ -}}
      {{block "xml.print_listener" .}}
    {{else if exists . "backends" -}}
      {{- /* Single service. */ -}}
      {{block "xml.print_service" . -}}
    {{else if exists . "pid" -}}
      {{- /* Core stat. */ -}}
      {{block "xml.core" . -}}
    {{else -}}
      {{- /* Backend listing. */ -}}
      {{block "xml.print_backend" . -}}
    {{end -}}
  {{end}}
</pound>
{{end}}
