...

Source file src/github.com/cybertec-postgresql/pgwatch/v3/internal/sources/yaml.go

Documentation: github.com/cybertec-postgresql/pgwatch/v3/internal/sources

     1  package sources
     2  
     3  // This file contains the implementation of the ReaderWriter interface for the YAML file.
     4  
     5  import (
     6  	"context"
     7  	"io/fs"
     8  	"os"
     9  	"path/filepath"
    10  	"slices"
    11  	"strings"
    12  
    13  	"gopkg.in/yaml.v3"
    14  )
    15  
    16  func NewYAMLSourcesReaderWriter(ctx context.Context, path string) (ReaderWriter, error) {
    17  	return &fileSourcesReaderWriter{
    18  		ctx:  ctx,
    19  		path: path,
    20  	}, nil
    21  }
    22  
    23  type fileSourcesReaderWriter struct {
    24  	ctx  context.Context
    25  	path string
    26  }
    27  
    28  func (fcr *fileSourcesReaderWriter) WriteSources(mds Sources) error {
    29  	yamlData, _ := yaml.Marshal(mds)
    30  	return os.WriteFile(fcr.path, yamlData, 0644)
    31  }
    32  
    33  func (fcr *fileSourcesReaderWriter) UpdateSource(md Source) error {
    34  	dbs, err := fcr.GetSources()
    35  	if err != nil {
    36  		return err
    37  	}
    38  	for i, db := range dbs {
    39  		if db.Name == md.Name {
    40  			dbs[i] = md
    41  			return fcr.WriteSources(dbs)
    42  		}
    43  	}
    44  	dbs = append(dbs, md)
    45  	return fcr.WriteSources(dbs)
    46  }
    47  
    48  func (fcr *fileSourcesReaderWriter) DeleteSource(name string) error {
    49  	dbs, err := fcr.GetSources()
    50  	if err != nil {
    51  		return err
    52  	}
    53  	dbs = slices.DeleteFunc(dbs, func(md Source) bool { return md.Name == name })
    54  	return fcr.WriteSources(dbs)
    55  }
    56  
    57  func (fcr *fileSourcesReaderWriter) GetSources() (dbs Sources, err error) {
    58  	var fi fs.FileInfo
    59  	if fi, err = os.Stat(fcr.path); err != nil {
    60  		return
    61  	}
    62  	switch mode := fi.Mode(); {
    63  	case mode.IsDir():
    64  		err = filepath.WalkDir(fcr.path, func(path string, d fs.DirEntry, err error) error {
    65  			if err != nil {
    66  				return err
    67  			}
    68  			name := strings.ToLower(d.Name())
    69  			if d.IsDir() || !strings.HasSuffix(name, ".yaml") && !strings.HasSuffix(name, ".yml") {
    70  				return nil
    71  			}
    72  			var mdbs Sources
    73  			if mdbs, err = fcr.getSources(path); err == nil {
    74  				dbs = append(dbs, mdbs...)
    75  			}
    76  			return err
    77  		})
    78  	case mode.IsRegular():
    79  		dbs, err = fcr.getSources(fcr.path)
    80  	}
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  	return dbs.Validate()
    85  }
    86  
    87  func (fcr *fileSourcesReaderWriter) getSources(configFilePath string) (dbs Sources, err error) {
    88  	var yamlFile []byte
    89  	if yamlFile, err = os.ReadFile(configFilePath); err != nil {
    90  		return
    91  	}
    92  	c := make(Sources, 0) // there can be multiple configs in a single file
    93  	if err = yaml.Unmarshal(yamlFile, &c); err != nil {
    94  		return
    95  	}
    96  	for _, v := range c {
    97  		dbs = append(dbs, fcr.expandEnvVars(v))
    98  	}
    99  	return
   100  }
   101  
   102  func (fcr *fileSourcesReaderWriter) expandEnvVars(md Source) Source {
   103  	if strings.HasPrefix(string(md.Kind), "$") {
   104  		md.Kind = Kind(os.ExpandEnv(string(md.Kind)))
   105  	}
   106  	if strings.HasPrefix(md.Name, "$") {
   107  		md.Name = os.ExpandEnv(md.Name)
   108  	}
   109  	if strings.HasPrefix(md.IncludePattern, "$") {
   110  		md.IncludePattern = os.ExpandEnv(md.IncludePattern)
   111  	}
   112  	if strings.HasPrefix(md.ExcludePattern, "$") {
   113  		md.ExcludePattern = os.ExpandEnv(md.ExcludePattern)
   114  	}
   115  	if strings.HasPrefix(md.PresetMetrics, "$") {
   116  		md.PresetMetrics = os.ExpandEnv(md.PresetMetrics)
   117  	}
   118  	if strings.HasPrefix(md.PresetMetricsStandby, "$") {
   119  		md.PresetMetricsStandby = os.ExpandEnv(md.PresetMetricsStandby)
   120  	}
   121  	return md
   122  }
   123