diff --git a/cmd/index_template.go b/cmd/index_template.go index 96b6084..363caf7 100644 --- a/cmd/index_template.go +++ b/cmd/index_template.go @@ -20,6 +20,7 @@ import ( "context" "errors" "fmt" + "slices" "codeberg.org/scip/esctl/pkg/cfg" "codeberg.org/scip/esctl/pkg/es" @@ -170,6 +171,10 @@ https://www.elastic.co/docs/reference/elasticsearch/index-settings return fmt.Errorf("no name specified") } + if !slices.Contains([]string{"standard", "timeseries", "logsdb", "lookup"}, conf.Mode) { + return errors.New("mode must be one of: standard, timeseries, logsdb or lookup") + } + mappings := args.Slice()[1:] if modify { diff --git a/pkg/es/index_template.go b/pkg/es/index_template.go index cd6e187..f25b471 100644 --- a/pkg/es/index_template.go +++ b/pkg/es/index_template.go @@ -22,7 +22,6 @@ import ( "errors" "fmt" "log/slog" - "slices" "strconv" "strings" @@ -185,34 +184,13 @@ func IndexTemplateCreate(conf *cfg.Config, name string, mappings []string) error } if conf.Mode != "" { - if !slices.Contains([]string{"standard", "timeseries", "logsdb", "lookup"}, conf.Mode) { - return errors.New("mode must be one of: standard, timeseries, logsdb or lookup") - } - settings = settings.Mode(conf.Mode) } if len(mappings) > 0 { - typemaps := esdsl.NewTypeMapping() - - for _, mapping := range mappings { - parts := strings.Split(mapping, ":") - if len(parts) != 2 { - return fmt.Errorf( - "invalid mapping %s, expect (type: integer, text, date, keyword)", - mapping) - } - - switch parts[1] { - case "text": - typemaps.AddProperty(parts[0], esdsl.NewTextProperty()) - case "integer": - typemaps.AddProperty(parts[0], esdsl.NewIntegerNumberProperty()) - case "date": - typemaps.AddProperty(parts[0], esdsl.NewDateProperty()) - case "keyword": - typemaps.AddProperty(parts[0], esdsl.NewKeywordProperty()) - } + typemaps, err := modMappings(mappings) + if err != nil { + return err } maps.Mappings(typemaps) @@ -227,40 +205,18 @@ func IndexTemplateCreate(conf *cfg.Config, name string, mappings []string) error } if len(conf.Meta) > 0 { - metadata := map[string]json.RawMessage{} - - for _, meta := range conf.Meta { - parts := strings.Split(meta, ":") - if len(parts) != 2 { - return errors.New("meta data must be in the form key:value") - } - - msg, err := json.Marshal(parts[1]) - if err != nil { - return fmt.Errorf("failed to json marshal metadata %s: %w", meta, err) - } - - metadata[parts[0]] = msg + metadata, err := modMeta(conf, nil) + if err != nil { + return err } create.Meta_(esdsl.NewMetadata(metadata)) } if len(conf.Settings) > 0 { - usersettings := map[string]json.RawMessage{} - - for _, meta := range conf.Settings { - parts := strings.Split(meta, ":") - if len(parts) != 2 { - return errors.New("settings data must be in the form key:value") - } - - msg, err := json.Marshal(parts[1]) - if err != nil { - return fmt.Errorf("failed to json marshal metadata %s: %w", meta, err) - } - - usersettings[parts[0]] = msg + usersettings, err := modSettings(conf) + if err != nil { + return err } settings = settings.IndexSettings(usersettings) @@ -315,15 +271,10 @@ func IndexTemplateModify(conf *cfg.Config, name string, mappings []string) error maps.Mappings(tpl.IndexTemplate.Template.Mappings) maps.Aliases(tpl.IndexTemplate.Template.Aliases) - // pre fill meta, if any - metadata := map[string]json.RawMessage{} - for key, value := range tpl.IndexTemplate.Meta_ { - metadata[key] = value - } - // pre fill components modify.ComposedOf(tpl.IndexTemplate.ComposedOf...) + // pre fill data stream config if conf.Stream { modify.DataStream(esdsl.NewDataStreamVisibility()) @@ -338,34 +289,13 @@ func IndexTemplateModify(conf *cfg.Config, name string, mappings []string) error modify.AllowAutoCreate(conf.AutoCreate) if conf.Mode != "" { - if !slices.Contains([]string{"standard", "timeseries", "logsdb", "lookup"}, conf.Mode) { - return errors.New("mode must be one of: standard, timeseries, logsdb or lookup") - } - *settings.Mode = conf.Mode } if len(mappings) > 0 { - typemaps := esdsl.NewTypeMapping() - - for _, mapping := range mappings { - parts := strings.Split(mapping, ":") - if len(parts) != 2 { - return fmt.Errorf( - "invalid mapping %s, expect (type: integer, text, date, keyword)", - mapping) - } - - switch parts[1] { - case "text": - typemaps.AddProperty(parts[0], esdsl.NewTextProperty()) - case "integer": - typemaps.AddProperty(parts[0], esdsl.NewIntegerNumberProperty()) - case "date": - typemaps.AddProperty(parts[0], esdsl.NewDateProperty()) - case "keyword": - typemaps.AddProperty(parts[0], esdsl.NewKeywordProperty()) - } + typemaps, err := modMappings(mappings) + if err != nil { + return err } maps.Mappings(typemaps) @@ -380,39 +310,19 @@ func IndexTemplateModify(conf *cfg.Config, name string, mappings []string) error } if len(conf.Meta) > 0 { - for _, meta := range conf.Meta { - parts := strings.Split(meta, ":") - if len(parts) != 2 { - return errors.New("meta data must be in the form key:value") - } - - msg, err := json.Marshal(parts[1]) - if err != nil { - return fmt.Errorf("failed to json marshal metadata %s: %w", meta, err) - } - - metadata[parts[0]] = msg + // pre fill meta, if any + metadata, err := modMeta(conf, tpl.IndexTemplate.Meta_) + if err != nil { + return err } + modify.Meta_(esdsl.NewMetadata(metadata)) } - modify.Meta_(esdsl.NewMetadata(metadata)) - if len(conf.Settings) > 0 { - usersettings := map[string]json.RawMessage{} - - for _, meta := range conf.Settings { - parts := strings.Split(meta, ":") - if len(parts) != 2 { - return errors.New("settings data must be in the form key:value") - } - - msg, err := json.Marshal(parts[1]) - if err != nil { - return fmt.Errorf("failed to json marshal metadata %s: %w", meta, err) - } - - usersettings[parts[0]] = msg + usersettings, err := modSettings(conf) + if err != nil { + return err } settings.IndexSettings = usersettings @@ -447,3 +357,73 @@ func IndexTemplateDelete(conf *cfg.Config, name string) error { return nil } + +func modMappings(mappings []string) (types.TypeMappingVariant, error) { + typemaps := esdsl.NewTypeMapping() + + for _, mapping := range mappings { + parts := strings.Split(mapping, ":") + if len(parts) != 2 { + return nil, fmt.Errorf( + "invalid mapping %s, expect (type: integer, text, date, keyword)", + mapping) + } + + switch parts[1] { + case "text": + typemaps.AddProperty(parts[0], esdsl.NewTextProperty()) + case "integer": + typemaps.AddProperty(parts[0], esdsl.NewIntegerNumberProperty()) + case "date": + typemaps.AddProperty(parts[0], esdsl.NewDateProperty()) + case "keyword": + typemaps.AddProperty(parts[0], esdsl.NewKeywordProperty()) + } + } + + return typemaps, nil +} + +func modMeta(conf *cfg.Config, meta types.Metadata) (map[string]json.RawMessage, error) { + metadata := map[string]json.RawMessage{} + + for key, value := range meta { + metadata[key] = value + } + + for _, meta := range conf.Meta { + parts := strings.Split(meta, ":") + if len(parts) != 2 { + return nil, errors.New("meta data must be in the form key:value") + } + + msg, err := json.Marshal(parts[1]) + if err != nil { + return nil, fmt.Errorf("failed to json marshal metadata %s: %w", meta, err) + } + + metadata[parts[0]] = msg + } + + return metadata, nil +} + +func modSettings(conf *cfg.Config) (map[string]json.RawMessage, error) { + usersettings := map[string]json.RawMessage{} + + for _, meta := range conf.Settings { + parts := strings.Split(meta, ":") + if len(parts) != 2 { + return nil, errors.New("settings data must be in the form key:value") + } + + msg, err := json.Marshal(parts[1]) + if err != nil { + return nil, fmt.Errorf("failed to json marshal metadata %s: %w", meta, err) + } + + usersettings[parts[0]] = msg + } + + return usersettings, nil +}