♲ Refactor configuration to use viper with context propagation
- Replace global ConfigPath and Overrides with viper-based configuration - Add viper.New() to create configurable viper instances - Store viper and unmarshaled Config struct in context for testability - Add RetrieveFromContext and AddToContext helper functions - Update files.Append to accept context and retrieve config from it - Update formatters.Preferred and formatters.New to accept context - Add PersistentPreRunE in CLI to create and configure viper instance - Support -c flag for custom config file path - Support -v flag for config value overrides - Update all test files to create viper and add to context - Remove unused config types and load functions - Add viper as dependency with automatic env var support (MYLOG_*)
This commit is contained in:
parent
d34363b8c0
commit
9f05f933dd
21 changed files with 338 additions and 360 deletions
|
|
@ -1,6 +1,7 @@
|
|||
package files
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
|
@ -11,11 +12,8 @@ import (
|
|||
"codeberg.org/danjones000/my-log/models"
|
||||
)
|
||||
|
||||
func Append(l models.Log) error {
|
||||
conf, err := config.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func Append(ctx context.Context, l models.Log) error {
|
||||
_, conf := config.RetrieveFromContext(ctx)
|
||||
|
||||
filename := l.Name
|
||||
if conf.Input.DotFolder {
|
||||
|
|
@ -27,7 +25,7 @@ func Append(l models.Log) error {
|
|||
}
|
||||
path := fp.Join(conf.Input.Path, filename)
|
||||
dir := fp.Dir(path)
|
||||
err = os.MkdirAll(dir, 0750)
|
||||
err := os.MkdirAll(dir, 0750)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package files
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
|
@ -10,6 +11,7 @@ import (
|
|||
"codeberg.org/danjones000/my-log/config"
|
||||
"codeberg.org/danjones000/my-log/models"
|
||||
"github.com/nalgeon/be"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func TestAppend(tt *testing.T) {
|
||||
|
|
@ -24,26 +26,25 @@ func TestAppend(tt *testing.T) {
|
|||
})
|
||||
tt.Run("failure", func(t *testing.T) {
|
||||
t.Run("badEntry", appendTestBadEntry)
|
||||
t.Run("load-err", appendTestConfLoadErr)
|
||||
t.Run("mkdir-err", appendTestMkdirErr)
|
||||
t.Run("append-log-err", appendTestOpenErr)
|
||||
})
|
||||
}
|
||||
|
||||
func setupAppendTest(t *testing.T) string {
|
||||
func setupAppendTest(t *testing.T) (string, context.Context) {
|
||||
t.Helper()
|
||||
dir := t.ArtifactDir()
|
||||
config.Overrides["input.path"] = dir
|
||||
config.Overrides["input.ext"] = "log"
|
||||
t.Cleanup(func() {
|
||||
delete(config.Overrides, "input.path")
|
||||
delete(config.Overrides, "input.ext")
|
||||
})
|
||||
return dir
|
||||
v := viper.New()
|
||||
v.SetConfigType("toml")
|
||||
v.Set("input.path", dir)
|
||||
v.Set("input.ext", "log")
|
||||
v.Set("input.dotFolder", false)
|
||||
ctx := config.AddToContext(t.Context(), v)
|
||||
return dir, ctx
|
||||
}
|
||||
|
||||
func appendTestSingle(t *testing.T) {
|
||||
dir := setupAppendTest(t)
|
||||
dir, ctx := setupAppendTest(t)
|
||||
when := time.Now().Local()
|
||||
e := models.Entry{
|
||||
Title: "Jimmy",
|
||||
|
|
@ -57,7 +58,7 @@ func appendTestSingle(t *testing.T) {
|
|||
Name: "test",
|
||||
Entries: []models.Entry{e},
|
||||
}
|
||||
err := Append(l)
|
||||
err := Append(ctx, l)
|
||||
be.Err(t, err, nil)
|
||||
by, err := os.ReadFile(dir + "/test.log")
|
||||
be.Err(t, err, nil)
|
||||
|
|
@ -68,7 +69,7 @@ func appendTestSingle(t *testing.T) {
|
|||
}
|
||||
|
||||
func appendTestTwoEntries(t *testing.T) {
|
||||
dir := setupAppendTest(t)
|
||||
dir, ctx := setupAppendTest(t)
|
||||
when := time.Now().Local()
|
||||
whens := when.Format(models.DateFormat)
|
||||
e := []models.Entry{
|
||||
|
|
@ -79,7 +80,7 @@ func appendTestTwoEntries(t *testing.T) {
|
|||
Name: "test",
|
||||
Entries: e,
|
||||
}
|
||||
err := Append(l)
|
||||
err := Append(ctx, l)
|
||||
be.Err(t, err, nil)
|
||||
by, _ := os.ReadFile(dir + "/test.log")
|
||||
st := string(by)
|
||||
|
|
@ -88,7 +89,7 @@ func appendTestTwoEntries(t *testing.T) {
|
|||
}
|
||||
|
||||
func appendTestAddNewLine(t *testing.T) {
|
||||
dir := setupAppendTest(t)
|
||||
dir, ctx := setupAppendTest(t)
|
||||
os.WriteFile(dir+"/test.log", []byte("foo"), 0644)
|
||||
when := time.Now().Local()
|
||||
whens := when.Format(models.DateFormat)
|
||||
|
|
@ -99,7 +100,7 @@ func appendTestAddNewLine(t *testing.T) {
|
|||
Name: "test",
|
||||
Entries: e,
|
||||
}
|
||||
err := Append(l)
|
||||
err := Append(ctx, l)
|
||||
be.Err(t, err, nil)
|
||||
by, _ := os.ReadFile(dir + "/test.log")
|
||||
exp := fmt.Sprintf("foo\n@begin %s - one\n@id jimmy @end\n", whens)
|
||||
|
|
@ -107,7 +108,7 @@ func appendTestAddNewLine(t *testing.T) {
|
|||
}
|
||||
|
||||
func appendTestDontAddNewLine(t *testing.T) {
|
||||
dir := setupAppendTest(t)
|
||||
dir, ctx := setupAppendTest(t)
|
||||
os.WriteFile(dir+"/test.log", []byte("foo\n"), 0644)
|
||||
when := time.Now().Local()
|
||||
whens := when.Format(models.DateFormat)
|
||||
|
|
@ -118,7 +119,7 @@ func appendTestDontAddNewLine(t *testing.T) {
|
|||
Name: "test",
|
||||
Entries: e,
|
||||
}
|
||||
err := Append(l)
|
||||
err := Append(ctx, l)
|
||||
be.Err(t, err, nil)
|
||||
by, _ := os.ReadFile(dir + "/test.log")
|
||||
exp := fmt.Sprintf("foo\n@begin %s - one\n@id jimmy @end\n", whens)
|
||||
|
|
@ -126,7 +127,7 @@ func appendTestDontAddNewLine(t *testing.T) {
|
|||
}
|
||||
|
||||
func appendTestBadEntry(t *testing.T) {
|
||||
dir := setupAppendTest(t)
|
||||
dir, ctx := setupAppendTest(t)
|
||||
e := models.Entry{
|
||||
Title: "Jimmy",
|
||||
}
|
||||
|
|
@ -134,19 +135,21 @@ func appendTestBadEntry(t *testing.T) {
|
|||
Name: "test",
|
||||
Entries: []models.Entry{e},
|
||||
}
|
||||
err := Append(l)
|
||||
err := Append(ctx, l)
|
||||
be.Err(t, err, nil)
|
||||
by, _ := os.ReadFile(dir + "/test.log")
|
||||
be.Equal(t, by, []byte{})
|
||||
}
|
||||
|
||||
func appendTestDotFolder(t *testing.T) {
|
||||
config.Overrides["input.dotFolder"] = "true"
|
||||
t.Cleanup(func() {
|
||||
delete(config.Overrides, "input.dotFolder")
|
||||
})
|
||||
dir := t.ArtifactDir()
|
||||
v := viper.New()
|
||||
v.SetConfigType("toml")
|
||||
v.Set("input.path", dir)
|
||||
v.Set("input.ext", "log")
|
||||
v.Set("input.dotFolder", true)
|
||||
ctx := config.AddToContext(t.Context(), v)
|
||||
|
||||
dir := setupAppendTest(t)
|
||||
e := models.Entry{
|
||||
Title: "something",
|
||||
Date: time.Now(),
|
||||
|
|
@ -155,7 +158,7 @@ func appendTestDotFolder(t *testing.T) {
|
|||
Name: "sub.test",
|
||||
Entries: []models.Entry{e},
|
||||
}
|
||||
err := Append(l)
|
||||
err := Append(ctx, l)
|
||||
be.Err(t, err, nil)
|
||||
by, err := os.ReadFile(dir + "/sub/test.log")
|
||||
be.Err(t, err, nil)
|
||||
|
|
@ -164,12 +167,7 @@ func appendTestDotFolder(t *testing.T) {
|
|||
}
|
||||
|
||||
func appendTestDotFolderNo(t *testing.T) {
|
||||
config.Overrides["input.dotFolder"] = "false"
|
||||
t.Cleanup(func() {
|
||||
delete(config.Overrides, "input.dotFolder")
|
||||
})
|
||||
|
||||
dir := setupAppendTest(t)
|
||||
dir, ctx := setupAppendTest(t)
|
||||
e := models.Entry{
|
||||
Title: "another",
|
||||
Date: time.Now(),
|
||||
|
|
@ -178,7 +176,7 @@ func appendTestDotFolderNo(t *testing.T) {
|
|||
Name: "sub.test",
|
||||
Entries: []models.Entry{e},
|
||||
}
|
||||
err := Append(l)
|
||||
err := Append(ctx, l)
|
||||
be.Err(t, err, nil)
|
||||
by, err := os.ReadFile(dir + "/sub.test.log")
|
||||
be.Err(t, err, nil)
|
||||
|
|
@ -187,11 +185,13 @@ func appendTestDotFolderNo(t *testing.T) {
|
|||
}
|
||||
|
||||
func appendTestNoExt(t *testing.T) {
|
||||
dir := setupAppendTest(t)
|
||||
config.Overrides["input.ext"] = ""
|
||||
t.Cleanup(func() {
|
||||
config.Overrides["input.ext"] = "log"
|
||||
})
|
||||
dir := t.ArtifactDir()
|
||||
v := viper.New()
|
||||
v.SetConfigType("toml")
|
||||
v.Set("input.path", dir)
|
||||
v.Set("input.ext", "")
|
||||
v.Set("input.dotFolder", false)
|
||||
ctx := config.AddToContext(t.Context(), v)
|
||||
|
||||
e := models.Entry{
|
||||
Title: "baz",
|
||||
|
|
@ -201,7 +201,7 @@ func appendTestNoExt(t *testing.T) {
|
|||
Name: "foobar",
|
||||
Entries: []models.Entry{e},
|
||||
}
|
||||
err := Append(l)
|
||||
err := Append(ctx, l)
|
||||
be.Err(t, err, nil)
|
||||
by, err := os.ReadFile(dir + "/foobar")
|
||||
be.Err(t, err, nil)
|
||||
|
|
@ -209,33 +209,20 @@ func appendTestNoExt(t *testing.T) {
|
|||
be.True(t, strings.Contains(st, fmt.Sprintf("@begin %s - %s", e.Date.Format(models.DateFormat), e.Title)))
|
||||
}
|
||||
|
||||
func appendTestConfLoadErr(t *testing.T) {
|
||||
dir := t.ArtifactDir()
|
||||
|
||||
currConf := config.ConfigPath
|
||||
tmp, _ := os.CreateTemp(dir, "app-conf-*.toml")
|
||||
fname := tmp.Name()
|
||||
t.Cleanup(func() { tmp.Close() })
|
||||
t.Cleanup(func() { os.Remove(fname) })
|
||||
fmt.Fprintln(tmp, `{"not":"toml"}`)
|
||||
config.ConfigPath = fname
|
||||
t.Cleanup(func() { config.ConfigPath = currConf })
|
||||
|
||||
err := Append(models.Log{})
|
||||
be.Err(t, err, "toml")
|
||||
}
|
||||
|
||||
func appendTestMkdirErr(t *testing.T) {
|
||||
// Don't run this test as root
|
||||
config.Overrides["input.path"] = "/var/my-logs-test"
|
||||
t.Cleanup(func() { delete(config.Overrides, "input.path") })
|
||||
v := viper.New()
|
||||
v.SetConfigType("toml")
|
||||
v.Set("input.path", "/var/my-logs-test")
|
||||
v.Set("input.ext", "log")
|
||||
v.Set("input.dotFolder", false)
|
||||
ctx := config.AddToContext(t.Context(), v)
|
||||
|
||||
err := Append(models.Log{})
|
||||
err := Append(ctx, models.Log{})
|
||||
be.Err(t, err, "permission denied")
|
||||
}
|
||||
|
||||
func appendTestOpenErr(t *testing.T) {
|
||||
dir := setupAppendTest(t)
|
||||
dir, ctx := setupAppendTest(t)
|
||||
l := models.Log{
|
||||
Name: "test-open-err",
|
||||
}
|
||||
|
|
@ -244,6 +231,6 @@ func appendTestOpenErr(t *testing.T) {
|
|||
f, _ := os.Create(fname)
|
||||
f.Close()
|
||||
os.Chmod(fname, 0400)
|
||||
err := Append(l)
|
||||
err := Append(ctx, l)
|
||||
be.Err(t, err, "permission denied")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue