В общем с использованием Grok получилось что-то такое:
- type: custom-api
title: PBS Backup Snapshots
cache: 12h
url: 'https://10.10.11.116:8007/api2/json/admin/datastore/s3-yandex/snapshots'
allow-insecure: true
headers:
Accept: application/json
Authorization: 'PBSAPIToken=myuser@pam!api:123'
options:
# Maximum storage size in bytes (default: 100 GB)
maxSize: 107374182400
template: |
<style>
.pbs-container { font-size: 0.9em; }
.backup-header, .backup-row { display: flex; border-collapse: collapse; align-items: center; gap: 10px; padding: 4px 0; }
.backup-row { text-transform: lowercase; border-bottom: 1px solid var(--color-border); }
.backup-header { text-transform: uppercase; font-size: 1em; font-weight: bold; color: var(--color-primary); border-bottom: 1px solid var(--color-primary); margin-bottom: 2px; }
.col { min-width: 0; margin-right: 15px; }
.col-id { flex: 1; }
.col-type { flex: 1; }
.col-comment { flex: 3; }
.col-size { flex: 1.5; text-align: right; }
.col-time { flex: 1.5; }
.total-summary { font-weight: bold; margin: 10px 0; padding: 5px; background: var(--color-background-secondary); border-radius: 4px; }
.stat-header { display: flex; justify-content: space-between; align-items: flex-end; font-size: 0.85em; margin: 10px 0; }
.stat-percent { font-weight: 500; }
.progress-bar { width: 100%; height: 8px; background: var(--color-background-tertiary); border-radius: 4px; overflow: hidden; margin-top: 4px; }
.progress-value { height: 100%; background: var(--color-positive); width: var(--percent, 0%); transition: width 0.3s ease; }
.progress-value-notice { background: var(--color-negative); }
.usage-label { text-align: center; margin-top: 5px; font-weight: 500; }
.server-type { padding: 2px 6px; border-radius: 4px; text-transform: lowercase; background: var(--color-background-tertiary); }
.timestamp { cursor: default; }
</style>
{{ if eq .Response.StatusCode 200 }}
<div class="pbs-container">
{{- $backups := .JSON.Array "data.#" -}}
{{- $sortedBackups := sortByFloat "backup-time" "desc" $backups -}}
{{- $bytesInGB := toFloat 1073741824 -}}
{{- $maxSize := .Options.FloatOr "maxSize" 107374182400 -}}
{{- $totalSize := 0 -}}
{{- range $sortedBackups -}}
{{- $totalSize = add $totalSize (.Int "size") -}}
{{- end -}}
{{- $usedPercentFloat := mul (div $totalSize $maxSize) 100 -}}
{{- $usedPercent := printf "%.1f" $usedPercentFloat -}}
{{- $usedPercentInt := toInt $usedPercentFloat -}}
<div class="backup-header">
<div class="col col-id">ID</div>
<div class="col col-type">TYPE</div>
<div class="col col-comment">COMMENT</div>
<div class="col col-size">SIZE</div>
<div class="col col-time">TIME</div>
</div>
{{- range $sortedBackups -}}
{{- $id := .String "backup-id" -}}
{{- $type := .String "backup-type" -}}
{{- $comment := .String "comment" -}}
{{- $size := .Int "size" -}}
{{- $time := .Int "backup-time" -}}
{{- $formattedSize := printf "%.2f GB" (div $size $bytesInGB) -}}
<div class="backup-row">
<div class="col col-id">{{ $id }}</div>
<div class="col col-type"><span class="server-type">{{ $type }}</span></div>
<div class="col col-comment">{{ $comment }}</div>
<div class="col col-size">{{ $formattedSize }}</div>
<div class="col col-time"><span class="timestamp" data-ts="{{ $time }}"></span></div>
</div>
{{- end -}}
<div class="total-summary">
Общий размер: {{ printf "%.2f GB" (div $totalSize $bytesInGB) }} ({{ $usedPercent }}% от {{ printf "%.2f GB" (div $maxSize $bytesInGB) }})
</div>
<div class="stat-header">
<span class="stat-percent">{{ $usedPercent }}%</span>
<span>Заполненность хранилища</span>
</div>
<div class="progress-bar">
<div class="progress-value{{ if ge $usedPercentInt 80 }} progress-value-notice{{ end }}" style="--percent: {{ $usedPercentInt }}"></div>
</div>
<div class="usage-label">Макс. размер: {{ printf "%.2f GB" (div $maxSize $bytesInGB) }}</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.timestamp').forEach(function(el) {
const ts = parseInt(el.dataset.ts) * 1000;
const date = new Date(ts);
el.textContent = date.toLocaleString('ru-RU', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
});
});
</script>
</div>
{{ else }}
<p>Ошибка загрузки: {{ .Response.Status }}</p>
{{ end }}
Проблема в том что в выводе в браузере получаю ошибку:
Get "https://10.10.11.116:8007/api2/json/admin/datastore/s3-yandex/snapshots": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
Сам PBS использует s3 от yandex, туда всё спокойно загрузилось и если дернуть запрос через curl то всё работает меньше чем за секунду:
curl -w "\n%{time_total}\n" -k -H "Accept: application/json" -H 'Authorization: PBSAPIToken=myuser@pam!api:123' "https://10.10.11.116:8007/api2/json/admin/datastore/s3-yandex/snapshots"
В общем что я делаю не так? Проблема действительно в запросе, или там что-то еще может быть? Гугление по теме увеличения таймаута лично мне ничего не дало(