fleet/orbit/pkg/token/reader.go
2022-10-10 17:15:35 -03:00

84 lines
1.8 KiB
Go

package token
import (
"os"
"sync"
"time"
)
// Reader is used to read the token value from a file
type Reader struct {
Path string // a path to a file containing a token
mu sync.Mutex // ensures atomic reads/writes; protects the following fields
cached string // the value of the token, a.k.a. the contents of the file
mtime time.Time // the mtime of the file when the token was last read
}
// Read returns the token value from the file only if the file is
// expired or the cached value is empty
func (r *Reader) Read() (string, error) {
changed, err := r.HasChanged()
if err != nil {
return "", err
}
if changed || r.GetCached() == "" {
if err := r.readFile(); err != nil {
return "", err
}
}
return r.GetCached(), nil
}
// HasChanged checks if the in-memory `value` has changed by comparing
// the chached `r.mtime` value with the `mtime` of the file at
// `r.path`
func (r *Reader) HasChanged() (bool, error) {
info, err := os.Stat(r.Path)
if err != nil {
return false, err
}
mtime := info.ModTime()
r.mu.Lock()
defer r.mu.Unlock()
return !mtime.Equal(r.mtime), nil
}
// HasExpired checks if 1 hour has passed since the last recorded `mtime` of
// the token file
func (r *Reader) HasExpired() bool {
r.mu.Lock()
defer r.mu.Unlock()
return time.Now().After(r.mtime.Add(1 * time.Hour))
}
func (r *Reader) GetMtime() time.Time {
r.mu.Lock()
defer r.mu.Unlock()
return r.mtime
}
// GetCached returns the cached token value
func (r *Reader) GetCached() string {
r.mu.Lock()
defer r.mu.Unlock()
return r.cached
}
func (r *Reader) readFile() error {
f, err := os.ReadFile(r.Path)
if err != nil {
return err
}
info, err := os.Stat(r.Path)
if err != nil {
return err
}
r.mu.Lock()
r.mtime = info.ModTime()
r.cached = string(f)
r.mu.Unlock()
return nil
}