Skip to content

Commit

Permalink
split file and fs provider
Browse files Browse the repository at this point in the history
  • Loading branch information
ktong committed Nov 12, 2023
1 parent b8c37e0 commit dd86f05
Show file tree
Hide file tree
Showing 22 changed files with 331 additions and 189 deletions.
4 changes: 4 additions & 0 deletions .github/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ component_management:
- component_id: konf
paths:
- "!provider/pflag/"
- "!provider/file/"
- component_id: file
paths:
- "provider/file/"
- component_id: pflag
paths:
- "provider/pflag/"
5 changes: 5 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ updates:
schedule:
interval: daily

- package-ecosystem: gomod
directory: /provider/file
schedule:
interval: daily

- package-ecosystem: gomod
directory: /provider/pflag
schedule:
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ jobs:
go-version: 'stable'
- name: Benchmark
run: go test -v -shuffle=on -bench=. ./...
- name: Benchmark (file)
run: go test -v -shuffle=on -bench=. ./...
working-directory: provider/file
- name: Benchmark (pflag)
run: go test -v -shuffle=on -bench=. ./...
working-directory: provider/pflag
3 changes: 3 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ jobs:
go-version: 'stable'
- name: Coverage
run: go test -v -covermode=count -coverprofile=coverage.txt ./...
- name: Coverage (file)
run: go test -v -covermode=count -coverprofile=coverage.txt ./...
working-directory: provider/file
- name: Coverage (pflag)
run: go test -v -covermode=count -coverprofile=coverage.txt ./...
working-directory: provider/pflag
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ jobs:
go-version: 'stable'
- name: Lint
uses: golangci/golangci-lint-action@v3
- name: Lint (file)
uses: golangci/golangci-lint-action@v3
with:
working-directory: provider/file
- name: Lint (pflag)
uses: golangci/golangci-lint-action@v3
with:
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ jobs:
run: go test -v -shuffle=on -count=10 -race ./...
- name: Test
run: go test -v -shuffle=on ./...
- name: Race Test (file)
run: go test -v -shuffle=on -count=10 -race ./...
working-directory: provider/file
- name: Test (file)
run: go test -v -shuffle=on ./...
working-directory: provider/file
- name: Race Test (pflag)
run: go test -v -shuffle=on -count=10 -race ./...
working-directory: provider/pflag
Expand Down
26 changes: 2 additions & 24 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@
package konf_test

import (
"context"
"embed"
"fmt"
"sync"
"time"

"github.com/ktong/konf"
"github.com/ktong/konf/provider/env"
"github.com/ktong/konf/provider/file"
pfs "github.com/ktong/konf/provider/fs"
)

func ExampleGet() {
Expand Down Expand Up @@ -41,32 +38,13 @@ func ExampleUnmarshal() {
// Output: example.com:8080
}

func ExampleWatch() {
ExampleSetGlobal()

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()

var waitGroup sync.WaitGroup
waitGroup.Add(1)
go func() {
if err := konf.Watch(ctx, func() {
fmt.Print(konf.Get[string]("server.host"))
}); err != nil {
panic(err)
}
}()
waitGroup.Wait()
// Output:
}

//go:embed testdata
var testdata embed.FS

func ExampleSetGlobal() {
cfg, err := konf.New(
konf.WithLoader(
file.New("testdata/config.json", file.WithFS(testdata)),
pfs.New(testdata, "testdata/config.json"),
env.New(env.WithPrefix("server")),
),
)
Expand Down
6 changes: 1 addition & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ module github.com/ktong/konf

go 1.21

require (
github.com/fsnotify/fsnotify v1.7.0
github.com/mitchellh/mapstructure v1.5.0
)
require github.com/mitchellh/mapstructure v1.5.0

require ( // for test
github.com/stretchr/testify v1.8.4
Expand All @@ -16,6 +13,5 @@ require ( // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.14.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
Expand All @@ -15,8 +13,6 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
17 changes: 2 additions & 15 deletions provider/file/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,16 @@ package file_test

import (
"testing"
"testing/fstest"

"github.com/stretchr/testify/require"

"github.com/ktong/konf/provider/file"
)

func BenchmarkNew(b *testing.B) {
mapFS := fstest.MapFS{
"config.json": {
Data: []byte(`{"k":"v"}`),
},
}
b.ResetTimer()

var loader file.File
for i := 0; i < b.N; i++ {
loader = file.New("config.json", file.WithFS(mapFS))
loader = file.New("testdata/config.json")
}
b.StopTimer()

Expand All @@ -32,12 +24,7 @@ func BenchmarkNew(b *testing.B) {
}

func BenchmarkLoad(b *testing.B) {
fs := fstest.MapFS{
"config.json": {
Data: []byte(`{"k":"v"}`),
},
}
loader := file.New("config.json", file.WithFS(fs))
loader := file.New("testdata/config.json")
b.ResetTimer()

var (
Expand Down
30 changes: 12 additions & 18 deletions provider/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,34 @@
package file

import (
"encoding/json"
"fmt"
"io/fs"
"log/slog"
"os"
)

// File is a Provider that loads configuration from file.
type File struct {
_ [0]func() // Ensure it's incomparable.
fs fs.FS
path string
unmarshal func([]byte, any) error
ignoreNotExist bool
}

// New returns a File with the given path and Option(s).
func New(path string, opts ...Option) File {
return File(apply(path, opts))
option := &options{
path: path,
unmarshal: json.Unmarshal,
}
for _, opt := range opts {
opt(option)
}

return File(*option)
}

func (f File) Load() (map[string]any, error) {
var (
bytes []byte
err error
)
if f.fs == nil {
bytes, err = os.ReadFile(f.path)
} else {
bytes, err = fs.ReadFile(f.fs, f.path)
}
bytes, err := os.ReadFile(f.path)
if err != nil {
if f.ignoreNotExist && os.IsNotExist(err) {
slog.Warn("Config file does not exist.", "file", f.path)
Expand All @@ -64,9 +62,5 @@ func (f File) Load() (map[string]any, error) {
}

func (f File) String() string {
if f.fs == nil {
return "os file:" + f.path
}

return "fs file:" + f.path
return "file:" + f.path
}
76 changes: 4 additions & 72 deletions provider/file/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,18 @@ package file_test
import (
"context"
"errors"
"io/fs"
"os"
"path/filepath"
"strings"
"sync"
"testing"
"testing/fstest"
"time"

"github.com/stretchr/testify/require"

"github.com/ktong/konf"
"github.com/ktong/konf/provider/file"
)

var (
_ konf.Loader = (*file.File)(nil)
_ konf.Watcher = (*file.File)(nil)
)

func TestFile_Load(t *testing.T) {
t.Parallel()

Expand All @@ -39,7 +31,7 @@ func TestFile_Load(t *testing.T) {
err string
}{
{
description: "os file",
description: "file",
path: "testdata/config.json",
expected: map[string]any{
"p": map[string]any{
Expand All @@ -48,49 +40,16 @@ func TestFile_Load(t *testing.T) {
},
},
{
description: "os file (not exist)",
description: "file (not exist)",
path: "not_found.json",
err: "read file: open not_found.json: ",
},
{
description: "os file (ignore not exist)",
description: "file (ignore not exist)",
path: "not_found.json",
opts: []file.Option{file.IgnoreFileNotExit()},
expected: map[string]any{},
},
{
description: "fs file",
path: "config.json",
opts: []file.Option{
file.WithFS(fstest.MapFS{
"config.json": {
Data: []byte(`{"p":{"k":"v"}}`),
},
}),
},
expected: map[string]any{
"p": map[string]any{
"k": "v",
},
},
},
{
description: "fs file (not exist)",
path: "not_found.json",
opts: []file.Option{
file.WithFS(fstest.MapFS{}),
},
err: "read file: open not_found.json: file does not exist",
},
{
description: "fs file (ignore not exist)",
path: "not_found.json",
opts: []file.Option{
file.WithFS(fstest.MapFS{}),
file.IgnoreFileNotExit(),
},
expected: map[string]any{},
},
{
description: "unmarshal error",
path: "testdata/config.json",
Expand Down Expand Up @@ -179,32 +138,5 @@ func TestFile_Watch(t *testing.T) {
func TestFile_String(t *testing.T) {
t.Parallel()

testcases := []struct {
description string
path string
fs fs.FS
expected string
}{
{
description: "fs file",
path: "config.json",
fs: fstest.MapFS{},
expected: "fs file:config.json",
},
{
description: "os file",
path: "config.json",
expected: "os file:config.json",
},
}

for i := range testcases {
testcase := testcases[i]

t.Run(testcase.description, func(t *testing.T) {
t.Parallel()

require.Equal(t, testcase.expected, file.New(testcase.path, file.WithFS(testcase.fs)).String())
})
}
require.Equal(t, "file:config.json", file.New("config.json").String())
}
14 changes: 14 additions & 0 deletions provider/file/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module github.com/ktong/konf/provider/file

go 1.21

require github.com/fsnotify/fsnotify v1.7.0

require github.com/stretchr/testify v1.8.4

require ( // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.14.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading

0 comments on commit dd86f05

Please sign in to comment.