Files
esctl/pkg/es/snapshot.go

157 lines
3.8 KiB
Go
Raw Permalink Normal View History

2026-04-22 13:38:02 +02:00
/*
Copyright © 2026 Thomas von Dein
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package es
import (
"context"
"errors"
"fmt"
"log/slog"
"regexp"
"strings"
"codeberg.org/scip/esctl/pkg/cfg"
"codeberg.org/scip/esctl/pkg/printer"
2026-04-22 13:38:02 +02:00
)
var (
findIndex = regexp.MustCompile(`^\d{4}\.\d{2}\.\d{2}\-(.*)\-timeseries`)
)
type Snapshot struct {
Name string
Forindex string
Orphaned string
Status string
Start string
IndexCount int
}
func SnapshotList(conf *cfg.Config) error {
// get partial indicies
ires, err := conf.DefaultCluster.ES.Cat.Indices().Do(context.Background())
2026-04-22 13:38:02 +02:00
if err != nil {
return fmt.Errorf("failed to get indicies: %s", esErrorString(err))
2026-04-22 13:38:02 +02:00
}
indicies := map[string]int{}
for _, index := range ires {
name := strings.ReplaceAll(*index.Index, "partial-", "")
indicies[name] = 1
}
// get snapshots
sres, err := conf.DefaultCluster.ES.Cat.Snapshots().Do(context.Background())
2026-04-22 13:38:02 +02:00
if err != nil {
return fmt.Errorf("failed to get snapshots: %s", esErrorString(err))
2026-04-22 13:38:02 +02:00
}
slog.Debug("ES result", "indicies", sres)
snapshots := []*Snapshot{} // original snapshot names
for _, snapshot := range sres {
snap := &Snapshot{
Name: *snapshot.Id,
Status: *snapshot.Status,
Start: fmt.Sprintf("%s", snapshot.StartTime),
Forindex: indexFromSnapshot(*snapshot.Id),
Orphaned: "no",
}
_, exists := indicies[snap.Forindex]
if !exists {
snap.Orphaned = "orphaned"
}
if (conf.Failed && snap.Orphaned == "orphaned") || !conf.Failed {
snapshots = append(snapshots, snap)
}
}
table := printer.NewTable(conf, 5, len(snapshots))
2026-04-22 13:38:02 +02:00
table.Addheaders("name", "index", "start", "orphaned", "status")
for idx, snap := range snapshots {
table.Entries[idx] = []string{
2026-04-22 13:38:02 +02:00
snap.Name,
snap.Forindex,
snap.Start,
snap.Orphaned,
snap.Status,
}
}
table.Sort()
if err := table.Print(); err != nil {
return err
}
2026-04-22 13:38:02 +02:00
return nil
}
func SnapshotShow(conf *cfg.Config, snapshot string) error {
res, err := conf.DefaultCluster.ES.Snapshot.Get("*", snapshot).Do(context.Background())
2026-04-22 13:38:02 +02:00
if err != nil {
return fmt.Errorf("failed to get snapshot: %s", esErrorString(err))
2026-04-22 13:38:02 +02:00
}
slog.Debug("ES result", "snapshot", res)
if res.Total == 0 {
return errors.New("no snapshot retrieved")
}
table := printer.NewTable(conf, 2, 17)
2026-05-18 13:58:08 +02:00
table.Addheaders("snapshot property", "value")
2026-04-22 13:38:02 +02:00
snap := res.Snapshots[0]
table.Entries = [][]string{
2026-04-22 13:38:02 +02:00
{"snapshot", snapshot},
{"uuid", snap.Uuid},
{"repository", *snap.Repository},
{"version_id", fmt.Sprintf("%d", snap.VersionId)},
{"version", *snap.Version},
{"include_global_state", fmt.Sprintf("%t", *snap.IncludeGlobalState)},
{"state", *snap.State},
{"start_time", fmt.Sprintf("%s", snap.StartTime)},
{"end_time", fmt.Sprintf("%s", snap.EndTime)},
{"duration_in_millis", fmt.Sprintf("%d", *snap.DurationInMillis)},
{"shards-total", fmt.Sprintf("%d", snap.Shards.Total)},
{"shards-failed", fmt.Sprintf("%d", snap.Shards.Failed)},
{"shards-successful", fmt.Sprintf("%d", snap.Shards.Successful)},
}
if err := table.Print(); err != nil {
return err
}
2026-04-22 13:38:02 +02:00
return nil
}
func indexFromSnapshot(snapshot string) string {
matches := findIndex.FindStringSubmatch(snapshot)
if len(matches) != 2 {
return ""
}
return matches[1]
}