~ogham/doom

543c2a0711e0efd72127932b7a94e9f1a15d6572 — Benjamin Sago 1 year, 10 months ago fe754de v0.6.1 v6.0.1
Secret appliers that can fail
1 files changed, 30 insertions(+), 8 deletions(-)

M msecrets/secrets.go
M msecrets/secrets.go => msecrets/secrets.go +30 -8
@@ 24,13 24,17 @@ import (
// wrapper, on the other hand, allows them to be updated upon receiving a signal.
type Secrets struct {
    path mpath.Path
    appliers map[string]func(string)
    appliers map[string]Applier
}

// An Applier is a function that does something with a secret value that’s just
// been loaded.
type Applier func(secretValue string)error

// New returns a new Secrets handler with the given path. New does not read the
// secrets when called by itself.
func New(path mpath.Path) *Secrets {
    return &Secrets{path, make(map[string]func(string))}
    return &Secrets{path, make(map[string]Applier)}
}

// Register registers a new secret applier, pairing a secret name with a function


@@ 42,7 46,7 @@ func New(path mpath.Path) *Secrets {
// making them thread-safe for THIS reason; however, you will almost certainly
// want to synchronise access to the memory that holds each secret behind a
// sync.Mutex or sync.RWMutex to prevent it from being read while being updated.
func (s *Secrets) Register(secretName string, applier func(secretValue string)) {
func (s *Secrets) Register(secretName string, applier Applier) {
    s.appliers[secretName] = applier
}



@@ 65,6 69,7 @@ func (s *Secrets) Read() {
    scanner := bufio.NewScanner(file)
    linum := 0
    secretsApplied := 0
    secretsFailed := 0
    for scanner.Scan() {
        line := scanner.Text()
        linum += 1


@@ 76,8 81,13 @@ func (s *Secrets) Read() {
        }

        if applier, matches := s.appliers[secretName]; matches {
            applier(secretValue)
            secretsApplied++
            err := applier(secretValue)
            if err != nil {
                log.Printf("Failed to set secret %q (line #%d): %v", secretName, linum, err)
                secretsFailed++
            } else {
                secretsApplied++
            }
        } else {
            log.Printf("Unknown secret %q (line #%d) in secrets file", secretName, linum)
        }


@@ 86,15 96,27 @@ func (s *Secrets) Read() {
    if err := scanner.Err(); err != nil {
        log.Printf("Failed to read from secrets file: %v", err)
    } else if secretsApplied == 0 {
        log.Println("No secrets applied.")
        log.Printf("No secrets applied (%d failed)", secretsFailed)
    } else if secretsApplied == 1 {
        log.Println("1 secret applied.")
        log.Printf("1 secret applied (%d failed)", secretsFailed)
    } else {
        log.Printf("%d secrets applied.", secretsApplied)
        log.Printf("%d secrets applied (%d failed)", secretsApplied, secretsFailed)
    }
}

// Infallibly converts a function that always succeeds to a function that always
// returns a nil error.
func Infallibly[T any](input func(T)) func(T)error {
    return func(secretValue T) error {
        input(secretValue)
        return nil
    }
}

//goland:noinspection GoUnusedConst
const SIGUSR1 = syscall.SIGUSR1
//goland:noinspection GoUnusedConst
const SIGUSR2 = syscall.SIGUSR2

// ListenForReload sets up the signal listener for the OS signal with the given
// value, wherein upon receiving a signal, runs Read.