feat: 增加ism管理接口
test: 索引模板和ism的单元测试和集成测试
This commit is contained in:
149
operations/index/policy.go
Normal file
149
operations/index/policy.go
Normal file
@@ -0,0 +1,149 @@
|
||||
// Package index provides index-level operations for OpenSearch.
|
||||
package index
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidPolicy is returned when the policy configuration is invalid.
|
||||
ErrInvalidPolicy = errors.New("invalid policy configuration")
|
||||
)
|
||||
|
||||
// PolicyManager defines the interface for managing index lifecycle policies.
|
||||
// This interface abstracts both AWS OpenSearch ISM (Index State Management)
|
||||
// and Elasticsearch ILM (Index Lifecycle Management) to provide a unified API.
|
||||
type PolicyManager interface {
|
||||
// PutPolicy creates or updates a lifecycle policy.
|
||||
PutPolicy(ctx context.Context, name string, policy *Policy) error
|
||||
|
||||
// GetPolicy retrieves a lifecycle policy by name.
|
||||
GetPolicy(ctx context.Context, name string) (*Policy, error)
|
||||
|
||||
// DeletePolicy deletes a lifecycle policy by name.
|
||||
DeletePolicy(ctx context.Context, name string) error
|
||||
|
||||
// ListPolicies retrieves all lifecycle policies.
|
||||
ListPolicies(ctx context.Context) (map[string]*Policy, error)
|
||||
}
|
||||
|
||||
// Policy represents a generic index lifecycle policy.
|
||||
// It can be converted to ISM (AWS OpenSearch) or ILM (Elasticsearch) format.
|
||||
type Policy struct {
|
||||
// Description of the policy
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// DefaultState is the initial state (ISM specific)
|
||||
DefaultState string `json:"default_state,omitempty"`
|
||||
|
||||
// States defines the lifecycle states (ISM format)
|
||||
States []State `json:"states,omitempty"`
|
||||
|
||||
// Phases defines the lifecycle phases (ILM format)
|
||||
// This field is used when targeting Elasticsearch
|
||||
Phases map[string]Phase `json:"phases,omitempty"`
|
||||
|
||||
// ISMTemplate for applying policy to indices (ISM specific)
|
||||
ISMTemplate []ISMTemplate `json:"ism_template,omitempty"`
|
||||
}
|
||||
|
||||
// State represents a state in ISM (AWS OpenSearch).
|
||||
type State struct {
|
||||
Name string `json:"name"`
|
||||
Actions []Action `json:"actions,omitempty"`
|
||||
Transitions []Transition `json:"transitions,omitempty"`
|
||||
}
|
||||
|
||||
// Action represents an action within a state.
|
||||
// In ISM, actions are serialized as a single key-value object where
|
||||
// the key is the action type and the value is the configuration.
|
||||
type Action struct {
|
||||
// Config contains the action type as the key and its configuration as the value
|
||||
// Example: {"rollover": {"min_index_age": "1d"}}
|
||||
Config map[string]interface{}
|
||||
}
|
||||
|
||||
// NewAction creates a new action with the specified type and configuration.
|
||||
func NewAction(actionType string, config map[string]interface{}) Action {
|
||||
return Action{
|
||||
Config: map[string]interface{}{
|
||||
actionType: config,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalJSON implements custom JSON marshaling for Action.
|
||||
// It directly marshals the Config map instead of wrapping it in a "Config" field.
|
||||
func (a Action) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(a.Config)
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements custom JSON unmarshaling for Action.
|
||||
func (a *Action) UnmarshalJSON(data []byte) error {
|
||||
return json.Unmarshal(data, &a.Config)
|
||||
}
|
||||
|
||||
// Transition defines when to move to the next state.
|
||||
type Transition struct {
|
||||
StateName string `json:"state_name"`
|
||||
Conditions *Conditions `json:"conditions,omitempty"`
|
||||
}
|
||||
|
||||
// Conditions defines the conditions for state transitions.
|
||||
type Conditions struct {
|
||||
MinIndexAge string `json:"min_index_age,omitempty"`
|
||||
MinDocCount *int64 `json:"min_doc_count,omitempty"`
|
||||
MinSize string `json:"min_size,omitempty"`
|
||||
}
|
||||
|
||||
// Phase represents a phase in ILM (Elasticsearch).
|
||||
// This is for future Elasticsearch compatibility.
|
||||
type Phase struct {
|
||||
MinAge string `json:"min_age,omitempty"`
|
||||
Actions map[string]interface{} `json:"actions,omitempty"`
|
||||
}
|
||||
|
||||
// ISMTemplate defines index patterns for automatic policy application.
|
||||
type ISMTemplate struct {
|
||||
IndexPatterns []string `json:"index_patterns"`
|
||||
Priority int `json:"priority"`
|
||||
}
|
||||
|
||||
// Validate checks if the policy configuration is valid.
|
||||
func (p *Policy) Validate() error {
|
||||
if p == nil {
|
||||
return ErrInvalidPolicy
|
||||
}
|
||||
|
||||
// For ISM: must have at least one state with a default_state
|
||||
if len(p.States) > 0 {
|
||||
if p.DefaultState == "" {
|
||||
return errors.New("default_state is required when states are defined")
|
||||
}
|
||||
|
||||
// Verify default_state exists in states
|
||||
found := false
|
||||
for _, state := range p.States {
|
||||
if state.Name == p.DefaultState {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return errors.New("default_state must match one of the defined states")
|
||||
}
|
||||
}
|
||||
|
||||
// For ILM: must have at least one phase
|
||||
if len(p.Phases) > 0 && len(p.States) > 0 {
|
||||
return errors.New("cannot define both ISM states and ILM phases in the same policy")
|
||||
}
|
||||
|
||||
if len(p.States) == 0 && len(p.Phases) == 0 {
|
||||
return errors.New("policy must define either states (ISM) or phases (ILM)")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user