github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/alertmanager/alertstore/local/store.go (about)

     1  package local
     2  
     3  import (
     4  	"context"
     5  	"flag"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  
    11  	"github.com/pkg/errors"
    12  	"github.com/prometheus/alertmanager/config"
    13  
    14  	"github.com/cortexproject/cortex/pkg/alertmanager/alertspb"
    15  )
    16  
    17  const (
    18  	Name = "local"
    19  )
    20  
    21  var (
    22  	errReadOnly = errors.New("local alertmanager config storage is read-only")
    23  	errState    = errors.New("local alertmanager storage does not support state persistency")
    24  )
    25  
    26  // StoreConfig configures a static file alertmanager store
    27  type StoreConfig struct {
    28  	Path string `yaml:"path"`
    29  }
    30  
    31  // RegisterFlags registers flags related to the alertmanager local storage.
    32  func (cfg *StoreConfig) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet) {
    33  	f.StringVar(&cfg.Path, prefix+"local.path", "", "Path at which alertmanager configurations are stored.")
    34  }
    35  
    36  // Store is used to load user alertmanager configs from a local disk
    37  type Store struct {
    38  	cfg StoreConfig
    39  }
    40  
    41  // NewStore returns a new file alert store.
    42  func NewStore(cfg StoreConfig) (*Store, error) {
    43  	return &Store{cfg}, nil
    44  }
    45  
    46  // ListAllUsers implements alertstore.AlertStore.
    47  func (f *Store) ListAllUsers(_ context.Context) ([]string, error) {
    48  	configs, err := f.reloadConfigs()
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  
    53  	userIDs := make([]string, 0, len(configs))
    54  	for userID := range configs {
    55  		userIDs = append(userIDs, userID)
    56  	}
    57  
    58  	return userIDs, nil
    59  }
    60  
    61  // GetAlertConfigs implements alertstore.AlertStore.
    62  func (f *Store) GetAlertConfigs(_ context.Context, userIDs []string) (map[string]alertspb.AlertConfigDesc, error) {
    63  	configs, err := f.reloadConfigs()
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  
    68  	filtered := make(map[string]alertspb.AlertConfigDesc, len(userIDs))
    69  	for _, userID := range userIDs {
    70  		if cfg, ok := configs[userID]; ok {
    71  			filtered[userID] = cfg
    72  		}
    73  	}
    74  
    75  	return filtered, nil
    76  }
    77  
    78  // GetAlertConfig implements alertstore.AlertStore.
    79  func (f *Store) GetAlertConfig(_ context.Context, user string) (alertspb.AlertConfigDesc, error) {
    80  	cfgs, err := f.reloadConfigs()
    81  	if err != nil {
    82  		return alertspb.AlertConfigDesc{}, err
    83  	}
    84  
    85  	cfg, exists := cfgs[user]
    86  
    87  	if !exists {
    88  		return alertspb.AlertConfigDesc{}, alertspb.ErrNotFound
    89  	}
    90  
    91  	return cfg, nil
    92  }
    93  
    94  // SetAlertConfig implements alertstore.AlertStore.
    95  func (f *Store) SetAlertConfig(_ context.Context, cfg alertspb.AlertConfigDesc) error {
    96  	return errReadOnly
    97  }
    98  
    99  // DeleteAlertConfig implements alertstore.AlertStore.
   100  func (f *Store) DeleteAlertConfig(_ context.Context, user string) error {
   101  	return errReadOnly
   102  }
   103  
   104  // ListUsersWithFullState implements alertstore.AlertStore.
   105  func (f *Store) ListUsersWithFullState(ctx context.Context) ([]string, error) {
   106  	return nil, errState
   107  }
   108  
   109  // GetFullState implements alertstore.AlertStore.
   110  func (f *Store) GetFullState(ctx context.Context, user string) (alertspb.FullStateDesc, error) {
   111  	return alertspb.FullStateDesc{}, errState
   112  }
   113  
   114  // SetFullState implements alertstore.AlertStore.
   115  func (f *Store) SetFullState(ctx context.Context, user string, cfg alertspb.FullStateDesc) error {
   116  	return errState
   117  }
   118  
   119  // DeleteFullState implements alertstore.AlertStore.
   120  func (f *Store) DeleteFullState(ctx context.Context, user string) error {
   121  	return errState
   122  }
   123  
   124  func (f *Store) reloadConfigs() (map[string]alertspb.AlertConfigDesc, error) {
   125  	configs := map[string]alertspb.AlertConfigDesc{}
   126  	err := filepath.Walk(f.cfg.Path, func(path string, info os.FileInfo, err error) error {
   127  		if err != nil {
   128  			return errors.Wrapf(err, "unable to walk file path at %s", path)
   129  		}
   130  
   131  		// Ignore files that are directories or not yaml files
   132  		ext := filepath.Ext(info.Name())
   133  		if info.IsDir() || (ext != ".yml" && ext != ".yaml") {
   134  			return nil
   135  		}
   136  
   137  		// Ensure the file is a valid Alertmanager Config.
   138  		_, err = config.LoadFile(path)
   139  		if err != nil {
   140  			return errors.Wrapf(err, "unable to load alertmanager config %s", path)
   141  		}
   142  
   143  		// Load the file to be returned by the store.
   144  		content, err := ioutil.ReadFile(path)
   145  		if err != nil {
   146  			return errors.Wrapf(err, "unable to read alertmanager config %s", path)
   147  		}
   148  
   149  		// The file name must correspond to the user tenant ID
   150  		user := strings.TrimSuffix(info.Name(), ext)
   151  
   152  		configs[user] = alertspb.AlertConfigDesc{
   153  			User:      user,
   154  			RawConfig: string(content),
   155  		}
   156  		return nil
   157  	})
   158  
   159  	return configs, err
   160  }