add ilm management support (#43)

This commit is contained in:
T. von Dein
2026-06-22 13:52:02 +02:00
parent 802217158c
commit 9b5ba0775b
9 changed files with 700 additions and 1 deletions

View File

@@ -31,6 +31,7 @@ const (
Crole
Ccluster
Capi
Cilm
)
func complete(cmd *cli.Command, what int) {
@@ -61,6 +62,8 @@ func complete(cmd *cli.Command, what int) {
list, err = es.DatastreamNames(conf)
case Capi:
list = es.ApiPathNames()
case Cilm:
list, err = es.IlmNames(conf)
}
if err != nil {

View File

@@ -197,3 +197,24 @@ func DatastreamRollover(conf *cfg.Config) *cli.Command {
},
}
}
func DatastreamIlm(conf *cfg.Config) *cli.Command {
return &cli.Command{
Name: "ilm",
Usage: "show ilm status",
UsageText: "ds ilm <name>",
ShellComplete: func(ctx context.Context, cmd *cli.Command) {
complete(cmd, Cdatastream)
},
Action: func(ctx context.Context, cmd *cli.Command) error {
ds := cmd.Args().Get(0)
if ds == "" {
return errors.New("no ds name specified")
}
return es.IlmExplain(conf, ds)
},
}
}

277
cmd/ilm.go Normal file
View File

@@ -0,0 +1,277 @@
/*
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 cmd
import (
"context"
"errors"
"codeberg.org/scip/esctl/pkg/cfg"
"codeberg.org/scip/esctl/pkg/es"
"github.com/urfave/cli/v3"
)
func Ilm(conf *cfg.Config) *cli.Command {
return &cli.Command{
Name: "ilm",
Usage: "manage index lifecycle",
Commands: []*cli.Command{
IlmRetry(conf),
IlmStatus(conf),
IlmList(conf),
IlmShow(conf),
IlmCreate(conf),
},
}
}
func IlmRetry(conf *cfg.Config) *cli.Command {
return &cli.Command{
Name: "retry",
Usage: "retry applying an ILM profile to an index",
UsageText: "retry <index>",
Action: func(ctx context.Context, cmd *cli.Command) error {
return es.IlmRetry(conf, cmd.Args().Get(0))
},
}
}
func IlmStatus(conf *cfg.Config) *cli.Command {
return &cli.Command{
Name: "status",
Usage: "get the current index lifecycle management status",
Action: func(ctx context.Context, cmd *cli.Command) error {
return es.IlmStatus(conf)
},
}
}
func IlmList(conf *cfg.Config) *cli.Command {
return &cli.Command{
Name: "list",
Aliases: []string{"ls"},
Usage: "list index lifecycle policies",
UsageText: "list [<policy-pattern>]",
Action: func(ctx context.Context, cmd *cli.Command) error {
return es.IlmList(conf, cmd.Args().Get(0))
},
}
}
func IlmShow(conf *cfg.Config) *cli.Command {
return &cli.Command{
Name: "show",
Aliases: []string{"sh"},
Usage: "show details about an index lifecycle policy",
UsageText: "show <policy>",
Action: func(ctx context.Context, cmd *cli.Command) error {
policy := cmd.Args().Get(0)
if policy == "" {
return errors.New("no policy specified")
}
return es.IlmShow(conf, cmd.Args().Get(0))
},
ShellComplete: func(ctx context.Context, cmd *cli.Command) {
complete(cmd, Cilm)
},
}
}
/*
*
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_primary_shard_size": "50gb",
"max_age": "1d",
"max_docs": 100000000
},
"set_priority": {
"priority": 100
}
}
},
"warm": {
"min_age": "7d",
"actions": {
"migrate": {},
"shrink": {
"number_of_shards": 1
},
"forcemerge": {
"max_num_segments": 1
},
"set_priority": {
"priority": 50
}
}
},
"cold": {
"min_age": "30d",
"actions": {
"migrate": {},
"searchable_snapshot": {
"snapshot_repository": "s3-logs-archive",
"force_merge_index": true
},
"set_priority": {
"priority": 0
}
}
},
"delete": {
"min_age": "90d",
"actions": {
"delete": {
"delete_searchable_snapshot": true
}
}
}
}
}
}
*/
func IlmCreate(conf *cfg.Config) *cli.Command {
return &cli.Command{
Name: "create",
Aliases: []string{"+"},
Usage: "create a index lifecycle policy",
UsageText: "create [options] <policy>",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "description",
Usage: "policy description",
Destination: &conf.Ilm.Description,
Aliases: []string{"D"},
},
// hot
&cli.StringFlag{
Name: "hot-min-age",
Usage: "hot phase: min age",
Destination: &conf.Ilm.HotMinAge,
},
&cli.StringFlag{
Name: "hot-rollover-max-age",
Usage: "hot phase: rollover after",
Destination: &conf.Ilm.HotRolloverMaxAge,
},
&cli.Int64Flag{
Name: "hot-rollover-max-primary-shard-size",
Usage: "hot phase: max primary shard size",
Destination: &conf.Ilm.HotRolloverMaxPrimaryShardSize,
},
&cli.Int64Flag{
Name: "hot-rollover-max-docs",
Usage: "hot phase: max docs",
Destination: &conf.Ilm.HotRolloverMaxDocs,
},
&cli.BoolFlag{
Name: "hot-readonly",
Usage: "hot phase: make index ro before rollover",
Destination: &conf.Ilm.HotReadonly,
},
// warm
&cli.StringFlag{
Name: "warm-min-age",
Usage: "warm phase: min age",
Destination: &conf.Ilm.WarmMinAge,
},
&cli.IntFlag{
Name: "warm-force-merge-segments",
Usage: "warm phase: force merge segments per shard",
Destination: &conf.Ilm.WarmForceMerge,
},
&cli.IntFlag{
Name: "warm-shrink-shards",
Usage: "warm phase: shrink on number of shards",
Destination: &conf.Ilm.WarmShrinkShards,
},
&cli.IntFlag{
Name: "warm-priority",
Usage: "warm phase: priority",
Destination: &conf.Ilm.WarmPriority,
},
// cold
&cli.StringFlag{
Name: "cold-min-age",
Usage: "cold phase: min age",
Destination: &conf.Ilm.ColdMinAge,
},
&cli.StringFlag{
Name: "cold-searchable-snapshot-repo",
Usage: "cold phase: searchable snapshot repo",
Destination: &conf.Ilm.ColdSearchableSnapshotRepo,
},
&cli.IntFlag{
Name: "cold-force-merge-segments",
Usage: "cold phase: force merge segments per shard",
Destination: &conf.Ilm.ColdForceMerge,
},
&cli.IntFlag{
Name: "cold-priority",
Usage: "cold phase: priority",
Destination: &conf.Ilm.ColdPriority,
},
// frozen
&cli.StringFlag{
Name: "frozen-min-age",
Usage: "frozen phase: min age",
Destination: &conf.Ilm.FrozenMinAge,
},
// delete
&cli.StringFlag{
Name: "delete-min-age",
Usage: "delete phase: min age",
Destination: &conf.Ilm.DeleteMinAge,
},
&cli.BoolFlag{
Name: "delete-searchable-snapshots",
Usage: "delete phase: delete searchable snapshots",
Destination: &conf.Ilm.DeleteSearchableSnapshots,
},
},
Action: func(ctx context.Context, cmd *cli.Command) error {
policy := cmd.Args().Get(0)
if policy == "" {
return errors.New("no policy name specified")
}
return es.IlmCreate(conf, cmd.Args().Get(0))
},
}
}

View File

@@ -42,6 +42,7 @@ func Index(conf *cfg.Config) *cli.Command {
IndexAllocation(conf),
IndexModify(conf),
IndexFields(conf),
IndexIlm(conf),
// sub commands
IndexAlias(conf),
@@ -300,3 +301,24 @@ func IndexFields(conf *cfg.Config) *cli.Command {
},
}
}
func IndexIlm(conf *cfg.Config) *cli.Command {
return &cli.Command{
Name: "ilm",
Usage: "show ilm status",
UsageText: "index ilm <index>",
ShellComplete: func(ctx context.Context, cmd *cli.Command) {
complete(cmd, Cindex)
},
Action: func(ctx context.Context, cmd *cli.Command) error {
index := cmd.Args().Get(0)
if index == "" {
return errors.New("no index specified")
}
return es.IlmExplain(conf, index)
},
}
}

View File

@@ -98,6 +98,7 @@ func Main() int {
Cluster(conf),
Ccr(conf),
Index(conf),
Ilm(conf),
Datastream(conf),
Shard(conf),
Snapshot(conf),