add snapshot commands

This commit is contained in:
2026-04-22 13:38:02 +02:00
parent a7d979ca38
commit 66221ea219
8 changed files with 298 additions and 10 deletions

View File

@@ -33,7 +33,7 @@ func Health(conf *cfg.Config) error {
slog.Debug("ES result", "cluster health", res)
table := NewTable(5)
table := NewTable(2, 5)
table.headers = []string{bold("SETTING"), bold("STATUS")}

View File

@@ -18,16 +18,23 @@ package es
import (
"context"
"log"
"fmt"
"log/slog"
"codeberg.org/scip/esctl/pkg/cfg"
"github.com/elastic/go-elasticsearch/v9/typedapi/types/enums/healthstatus"
)
func IndexList(conf *cfg.Config) error {
res, err := conf.ES.Cat.Indices().Do(context.Background())
cat := conf.ES.Cat.Indices()
if conf.Failed {
cat = cat.Health(healthstatus.Red)
}
res, err := cat.Do(context.Background())
if err != nil {
log.Fatalf("Error getting indicies: %s", err)
return fmt.Errorf("Error getting indicies: %s", err)
}
slog.Debug("ES result", "indicies", res)
@@ -40,9 +47,8 @@ func IndexList(conf *cfg.Config) error {
}
}
table := NewTable(size)
table.headers = []string{bold("NAME"), bold("SIZE"), bold("DOCSCOUNT")}
table := NewTable(3, size)
table.Addheaders("name", "size", "docscount")
for idx, index := range res {
name := Colorize(*index.Health, *index.Index)
@@ -59,3 +65,16 @@ func IndexList(conf *cfg.Config) error {
return nil
}
func IndexShow(conf *cfg.Config, index string) error {
res, err := conf.ES.Indices.Get(index).Do(context.Background())
if err != nil {
return fmt.Errorf("failed to get index: %s", err)
}
slog.Debug("ES result", "index", res)
// FIXME: add table printer like SnapshotShow
return nil
}

151
pkg/es/snapshot.go Normal file
View File

@@ -0,0 +1,151 @@
/*
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"
)
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.ES.Cat.Indices().Do(context.Background())
if err != nil {
return fmt.Errorf("Error getting indicies: %s", err)
}
indicies := map[string]int{}
for _, index := range ires {
name := strings.ReplaceAll(*index.Index, "partial-", "")
indicies[name] = 1
}
// get snapshots
sres, err := conf.ES.Cat.Snapshots().Do(context.Background())
if err != nil {
return fmt.Errorf("Error getting snapshots: %s", err)
}
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 := NewTable(5, len(snapshots))
table.Addheaders("name", "index", "start", "orphaned", "status")
for idx, snap := range snapshots {
table.entries[idx] = []string{
snap.Name,
snap.Forindex,
snap.Start,
snap.Orphaned,
snap.Status,
}
}
table.Sort()
table.PrintMarkdown()
return nil
}
func SnapshotShow(conf *cfg.Config, snapshot string) error {
res, err := conf.ES.Snapshot.Get("*", snapshot).Do(context.Background())
if err != nil {
return fmt.Errorf("failed to get snapshot: %s", err)
}
slog.Debug("ES result", "snapshot", res)
if res.Total == 0 {
return errors.New("no snapshot retrieved")
}
table := NewTable(2, 17)
table.Addheaders("field", "value")
snap := res.Snapshots[0]
table.entries = [][]string{
{"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)},
}
table.PrintMarkdown()
return nil
}
func indexFromSnapshot(snapshot string) string {
matches := findIndex.FindStringSubmatch(snapshot)
if len(matches) != 2 {
return ""
}
return matches[1]
}

View File

@@ -31,11 +31,11 @@ type Table struct {
entries [][]string
}
func NewTable(size int) *Table {
func NewTable(columns, rows int) *Table {
table := Table{}
table.headers = make([]string, size)
table.entries = make([][]string, size)
table.headers = make([]string, columns)
table.entries = make([][]string, rows)
return &table
}
@@ -106,3 +106,9 @@ func (data *Table) Sort() {
return data.entries[i][0] < data.entries[j][0]
})
}
func (data *Table) Addheaders(headers ...string) {
for idx, header := range headers {
data.headers[idx] = bold(strings.ToUpper(header))
}
}